mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-25 03:40:40 +00:00
Merge branch 'fix_work_queue' into 'master'
Fix hang on exit (#6145) Closes #6145 See merge request OpenMW/openmw!1004
This commit is contained in:
commit
1da644668f
@ -427,7 +427,8 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
|
|||||||
|
|
||||||
OMW::Engine::~Engine()
|
OMW::Engine::~Engine()
|
||||||
{
|
{
|
||||||
mWorkQueue->stop();
|
if (mScreenCaptureOperation != nullptr)
|
||||||
|
mScreenCaptureOperation->stop();
|
||||||
|
|
||||||
mEnvironment.cleanup();
|
mEnvironment.cleanup();
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ namespace Resource
|
|||||||
namespace SceneUtil
|
namespace SceneUtil
|
||||||
{
|
{
|
||||||
class WorkQueue;
|
class WorkQueue;
|
||||||
|
class AsyncScreenCaptureOperation;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace VFS
|
namespace VFS
|
||||||
@ -67,7 +68,7 @@ namespace OMW
|
|||||||
boost::filesystem::path mResDir;
|
boost::filesystem::path mResDir;
|
||||||
osg::ref_ptr<osgViewer::Viewer> mViewer;
|
osg::ref_ptr<osgViewer::Viewer> mViewer;
|
||||||
osg::ref_ptr<osgViewer::ScreenCaptureHandler> mScreenCaptureHandler;
|
osg::ref_ptr<osgViewer::ScreenCaptureHandler> mScreenCaptureHandler;
|
||||||
osg::ref_ptr<osgViewer::ScreenCaptureHandler::CaptureOperation> mScreenCaptureOperation;
|
osg::ref_ptr<SceneUtil::AsyncScreenCaptureOperation> mScreenCaptureOperation;
|
||||||
std::string mCellName;
|
std::string mCellName;
|
||||||
std::vector<std::string> mContentFiles;
|
std::vector<std::string> mContentFiles;
|
||||||
std::vector<std::string> mGroundcoverFiles;
|
std::vector<std::string> mGroundcoverFiles;
|
||||||
|
@ -492,7 +492,7 @@ namespace MWRender
|
|||||||
|
|
||||||
workItem->mTextures.emplace_back("textures/_land_default.dds");
|
workItem->mTextures.emplace_back("textures/_land_default.dds");
|
||||||
|
|
||||||
mWorkQueue->addWorkItem(workItem);
|
mWorkQueue->addWorkItem(std::move(workItem));
|
||||||
}
|
}
|
||||||
|
|
||||||
double RenderingManager::getReferenceTime() const
|
double RenderingManager::getReferenceTime() const
|
||||||
|
@ -317,7 +317,7 @@ namespace MWWorld
|
|||||||
if (found->second.mWorkItem)
|
if (found->second.mWorkItem)
|
||||||
{
|
{
|
||||||
found->second.mWorkItem->abort();
|
found->second.mWorkItem->abort();
|
||||||
mUnrefQueue->push(mPreloadCells[cell].mWorkItem);
|
mUnrefQueue->push(std::move(found->second.mWorkItem));
|
||||||
}
|
}
|
||||||
|
|
||||||
mPreloadCells.erase(found);
|
mPreloadCells.erase(found);
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <limits>
|
#include <limits>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
#include <BulletCollision/CollisionDispatch/btCollisionObject.h>
|
#include <BulletCollision/CollisionDispatch/btCollisionObject.h>
|
||||||
#include <BulletCollision/CollisionShapes/btCompoundShape.h>
|
#include <BulletCollision/CollisionShapes/btCompoundShape.h>
|
||||||
@ -867,6 +868,11 @@ namespace MWWorld
|
|||||||
|
|
||||||
Scene::~Scene()
|
Scene::~Scene()
|
||||||
{
|
{
|
||||||
|
for (const osg::ref_ptr<SceneUtil::WorkItem>& v : mWorkItems)
|
||||||
|
v->abort();
|
||||||
|
|
||||||
|
for (const osg::ref_ptr<SceneUtil::WorkItem>& v : mWorkItems)
|
||||||
|
v->waitTillDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Scene::hasCellChanged() const
|
bool Scene::hasCellChanged() const
|
||||||
@ -1061,6 +1067,9 @@ namespace MWWorld
|
|||||||
|
|
||||||
void doWork() override
|
void doWork() override
|
||||||
{
|
{
|
||||||
|
if (mAborted)
|
||||||
|
return;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
mSceneManager->getTemplate(mMesh);
|
mSceneManager->getTemplate(mMesh);
|
||||||
@ -1069,9 +1078,16 @@ namespace MWWorld
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void abort() override
|
||||||
|
{
|
||||||
|
mAborted = true;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string mMesh;
|
std::string mMesh;
|
||||||
Resource::SceneManager* mSceneManager;
|
Resource::SceneManager* mSceneManager;
|
||||||
|
std::atomic_bool mAborted {false};
|
||||||
};
|
};
|
||||||
|
|
||||||
void Scene::preload(const std::string &mesh, bool useAnim)
|
void Scene::preload(const std::string &mesh, bool useAnim)
|
||||||
@ -1081,7 +1097,13 @@ namespace MWWorld
|
|||||||
mesh_ = Misc::ResourceHelpers::correctActorModelPath(mesh_, mRendering.getResourceSystem()->getVFS());
|
mesh_ = Misc::ResourceHelpers::correctActorModelPath(mesh_, mRendering.getResourceSystem()->getVFS());
|
||||||
|
|
||||||
if (!mRendering.getResourceSystem()->getSceneManager()->checkLoaded(mesh_, mRendering.getReferenceTime()))
|
if (!mRendering.getResourceSystem()->getSceneManager()->checkLoaded(mesh_, mRendering.getReferenceTime()))
|
||||||
mRendering.getWorkQueue()->addWorkItem(new PreloadMeshItem(mesh_, mRendering.getResourceSystem()->getSceneManager()));
|
{
|
||||||
|
osg::ref_ptr<PreloadMeshItem> item(new PreloadMeshItem(mesh_, mRendering.getResourceSystem()->getSceneManager()));
|
||||||
|
mRendering.getWorkQueue()->addWorkItem(item);
|
||||||
|
const auto isDone = [] (const osg::ref_ptr<SceneUtil::WorkItem>& v) { return v->isDone(); };
|
||||||
|
mWorkItems.erase(std::remove_if(mWorkItems.begin(), mWorkItems.end(), isDone), mWorkItems.end());
|
||||||
|
mWorkItems.emplace_back(std::move(item));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::preloadCells(float dt)
|
void Scene::preloadCells(float dt)
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <osg/Vec4i>
|
#include <osg/Vec4i>
|
||||||
#include <osg/Vec2i>
|
#include <osg/Vec2i>
|
||||||
|
#include <osg/ref_ptr>
|
||||||
|
|
||||||
#include "ptr.hpp"
|
#include "ptr.hpp"
|
||||||
#include "globals.hpp"
|
#include "globals.hpp"
|
||||||
@ -10,6 +11,7 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <components/misc/constants.hpp>
|
#include <components/misc/constants.hpp>
|
||||||
|
|
||||||
@ -49,6 +51,11 @@ namespace MWPhysics
|
|||||||
class PhysicsSystem;
|
class PhysicsSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace SceneUtil
|
||||||
|
{
|
||||||
|
class WorkItem;
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
class Player;
|
class Player;
|
||||||
@ -91,6 +98,8 @@ namespace MWWorld
|
|||||||
|
|
||||||
std::set<ESM::RefNum> mPagedRefs;
|
std::set<ESM::RefNum> mPagedRefs;
|
||||||
|
|
||||||
|
std::vector<osg::ref_ptr<SceneUtil::WorkItem>> mWorkItems;
|
||||||
|
|
||||||
void insertCell (CellStore &cell, Loading::Listener* loadingListener, bool onlyObjects, bool test = false);
|
void insertCell (CellStore &cell, Loading::Listener* loadingListener, bool onlyObjects, bool test = false);
|
||||||
osg::Vec2i mCurrentGridCenter;
|
osg::Vec2i mCurrentGridCenter;
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@ -32,6 +33,9 @@ namespace
|
|||||||
|
|
||||||
void doWork() override
|
void doWork() override
|
||||||
{
|
{
|
||||||
|
if (mAborted)
|
||||||
|
return;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
(*mImpl)(*mImage, mContextId);
|
(*mImpl)(*mImage, mContextId);
|
||||||
@ -42,10 +46,16 @@ namespace
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void abort() override
|
||||||
|
{
|
||||||
|
mAborted = true;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const osg::ref_ptr<osgViewer::ScreenCaptureHandler::CaptureOperation> mImpl;
|
const osg::ref_ptr<osgViewer::ScreenCaptureHandler::CaptureOperation> mImpl;
|
||||||
const osg::ref_ptr<const osg::Image> mImage;
|
const osg::ref_ptr<const osg::Image> mImage;
|
||||||
const unsigned int mContextId;
|
const unsigned int mContextId;
|
||||||
|
std::atomic_bool mAborted {false};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,8 +140,27 @@ namespace SceneUtil
|
|||||||
assert(mImpl != nullptr);
|
assert(mImpl != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AsyncScreenCaptureOperation::~AsyncScreenCaptureOperation()
|
||||||
|
{
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncScreenCaptureOperation::stop()
|
||||||
|
{
|
||||||
|
for (const osg::ref_ptr<SceneUtil::WorkItem>& item : *mWorkItems.lockConst())
|
||||||
|
item->abort();
|
||||||
|
|
||||||
|
for (const osg::ref_ptr<SceneUtil::WorkItem>& item : *mWorkItems.lockConst())
|
||||||
|
item->waitTillDone();
|
||||||
|
}
|
||||||
|
|
||||||
void AsyncScreenCaptureOperation::operator()(const osg::Image& image, const unsigned int context_id)
|
void AsyncScreenCaptureOperation::operator()(const osg::Image& image, const unsigned int context_id)
|
||||||
{
|
{
|
||||||
mQueue->addWorkItem(new ScreenCaptureWorkItem(mImpl, image, context_id));
|
osg::ref_ptr<SceneUtil::WorkItem> item(new ScreenCaptureWorkItem(mImpl, image, context_id));
|
||||||
|
mQueue->addWorkItem(item);
|
||||||
|
const auto isDone = [] (const osg::ref_ptr<SceneUtil::WorkItem>& v) { return v->isDone(); };
|
||||||
|
const auto workItems = mWorkItems.lock();
|
||||||
|
workItems->erase(std::remove_if(workItems->begin(), workItems->end(), isDone), workItems->end());
|
||||||
|
workItems->emplace_back(std::move(item));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
#ifndef OPENMW_COMPONENTS_SCENEUTIL_SCREENCAPTURE_H
|
#ifndef OPENMW_COMPONENTS_SCENEUTIL_SCREENCAPTURE_H
|
||||||
#define OPENMW_COMPONENTS_SCENEUTIL_SCREENCAPTURE_H
|
#define OPENMW_COMPONENTS_SCENEUTIL_SCREENCAPTURE_H
|
||||||
|
|
||||||
|
#include <components/misc/guarded.hpp>
|
||||||
|
|
||||||
#include <osg/ref_ptr>
|
#include <osg/ref_ptr>
|
||||||
#include <osgViewer/ViewerEventHandlers>
|
#include <osgViewer/ViewerEventHandlers>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace osg
|
namespace osg
|
||||||
{
|
{
|
||||||
@ -14,6 +17,7 @@ namespace osg
|
|||||||
namespace SceneUtil
|
namespace SceneUtil
|
||||||
{
|
{
|
||||||
class WorkQueue;
|
class WorkQueue;
|
||||||
|
class WorkItem;
|
||||||
|
|
||||||
std::string writeScreenshotToFile(const std::string& screenshotPath, const std::string& screenshotFormat,
|
std::string writeScreenshotToFile(const std::string& screenshotPath, const std::string& screenshotFormat,
|
||||||
const osg::Image& image);
|
const osg::Image& image);
|
||||||
@ -38,11 +42,16 @@ namespace SceneUtil
|
|||||||
AsyncScreenCaptureOperation(osg::ref_ptr<SceneUtil::WorkQueue> queue,
|
AsyncScreenCaptureOperation(osg::ref_ptr<SceneUtil::WorkQueue> queue,
|
||||||
osg::ref_ptr<osgViewer::ScreenCaptureHandler::CaptureOperation> impl);
|
osg::ref_ptr<osgViewer::ScreenCaptureHandler::CaptureOperation> impl);
|
||||||
|
|
||||||
|
~AsyncScreenCaptureOperation();
|
||||||
|
|
||||||
|
void stop();
|
||||||
|
|
||||||
void operator()(const osg::Image& image, const unsigned int context_id) override;
|
void operator()(const osg::Image& image, const unsigned int context_id) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const osg::ref_ptr<SceneUtil::WorkQueue> mQueue;
|
const osg::ref_ptr<SceneUtil::WorkQueue> mQueue;
|
||||||
const osg::ref_ptr<osgViewer::ScreenCaptureHandler::CaptureOperation> mImpl;
|
const osg::ref_ptr<osgViewer::ScreenCaptureHandler::CaptureOperation> mImpl;
|
||||||
|
Misc::ScopeGuarded<std::vector<osg::ref_ptr<SceneUtil::WorkItem>>> mWorkItems;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,9 +74,9 @@ void WorkQueue::addWorkItem(osg::ref_ptr<WorkItem> item, bool front)
|
|||||||
|
|
||||||
std::unique_lock<std::mutex> lock(mMutex);
|
std::unique_lock<std::mutex> lock(mMutex);
|
||||||
if (front)
|
if (front)
|
||||||
mQueue.push_front(item);
|
mQueue.push_front(std::move(item));
|
||||||
else
|
else
|
||||||
mQueue.push_back(item);
|
mQueue.push_back(std::move(item));
|
||||||
mCondition.notify_one();
|
mCondition.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,12 +89,11 @@ osg::ref_ptr<WorkItem> WorkQueue::removeWorkItem()
|
|||||||
}
|
}
|
||||||
if (!mQueue.empty())
|
if (!mQueue.empty())
|
||||||
{
|
{
|
||||||
osg::ref_ptr<WorkItem> item = mQueue.front();
|
osg::ref_ptr<WorkItem> item = std::move(mQueue.front());
|
||||||
mQueue.pop_front();
|
mQueue.pop_front();
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
else
|
return nullptr;
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int WorkQueue::getNumItems() const
|
unsigned int WorkQueue::getNumItems() const
|
||||||
|
Loading…
x
Reference in New Issue
Block a user