1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-03-23 19:20:56 +00:00

Use correct frame and stats for lua worker

When a loading screen appears during the frame processing, the frame number
returned by the viewer is incremented and the stats reporting goes into the
wrong frame. Pass frame number and stats object from the main thread to avoid
this.
This commit is contained in:
elsid 2024-04-24 11:09:13 +02:00
parent 5f926bd129
commit b4976354a5
No known key found for this signature in database
GPG Key ID: 4DE04C198CBA7625
3 changed files with 37 additions and 28 deletions

View File

@ -340,11 +340,12 @@ bool OMW::Engine::frame(float frametime)
mWorld->updateWindowManager();
}
mLuaWorker->allowUpdate(); // if there is a separate Lua thread, it starts the update now
// if there is a separate Lua thread, it starts the update now
mLuaWorker->allowUpdate(frameStart, frameNumber, *stats);
mViewer->renderingTraversals();
mLuaWorker->finishUpdate();
mLuaWorker->finishUpdate(frameStart, frameNumber, *stats);
return true;
}
@ -910,7 +911,7 @@ void OMW::Engine::prepareEngine()
mLuaManager->init();
// starts a separate lua thread if "lua num threads" > 0
mLuaWorker = std::make_unique<MWLua::Worker>(*mLuaManager, *mViewer);
mLuaWorker = std::make_unique<MWLua::Worker>(*mLuaManager);
}
// Initialise and enter main loop.

View File

@ -7,13 +7,12 @@
#include <components/debug/debuglog.hpp>
#include <components/settings/values.hpp>
#include <osgViewer/Viewer>
#include <cassert>
namespace MWLua
{
Worker::Worker(LuaManager& manager, osgViewer::Viewer& viewer)
Worker::Worker(LuaManager& manager)
: mManager(manager)
, mViewer(viewer)
{
if (Settings::lua().mLuaNumThreads > 0)
mThread = std::thread([this] { run(); });
@ -29,26 +28,26 @@ namespace MWLua
}
}
void Worker::allowUpdate()
void Worker::allowUpdate(osg::Timer_t frameStart, unsigned frameNumber, osg::Stats& stats)
{
if (!mThread)
return;
{
std::lock_guard<std::mutex> lk(mMutex);
mUpdateRequest = true;
mUpdateRequest = UpdateRequest{ .mFrameStart = frameStart, .mFrameNumber = frameNumber, .mStats = &stats };
}
mCV.notify_one();
}
void Worker::finishUpdate()
void Worker::finishUpdate(osg::Timer_t frameStart, unsigned frameNumber, osg::Stats& stats)
{
if (mThread)
{
std::unique_lock<std::mutex> lk(mMutex);
mCV.wait(lk, [&] { return !mUpdateRequest; });
mCV.wait(lk, [&] { return !mUpdateRequest.has_value(); });
}
else
update();
update(frameStart, frameNumber, stats);
}
void Worker::join()
@ -64,12 +63,10 @@ namespace MWLua
}
}
void Worker::update()
void Worker::update(osg::Timer_t frameStart, unsigned frameNumber, osg::Stats& stats)
{
const osg::Timer_t frameStart = mViewer.getStartTick();
const unsigned int frameNumber = mViewer.getFrameStamp()->getFrameNumber();
OMW::ScopedProfile<OMW::UserStatsType::Lua> profile(
frameStart, frameNumber, *osg::Timer::instance(), *mViewer.getViewerStats());
const osg::Timer* const timer = osg::Timer::instance();
OMW::ScopedProfile<OMW::UserStatsType::Lua> profile(frameStart, frameNumber, *timer, stats);
mManager.update();
}
@ -79,20 +76,22 @@ namespace MWLua
while (true)
{
std::unique_lock<std::mutex> lk(mMutex);
mCV.wait(lk, [&] { return mUpdateRequest || mJoinRequest; });
mCV.wait(lk, [&] { return mUpdateRequest.has_value() || mJoinRequest; });
if (mJoinRequest)
break;
assert(mUpdateRequest.has_value());
try
{
update();
update(mUpdateRequest->mFrameStart, mUpdateRequest->mFrameNumber, *mUpdateRequest->mStats);
}
catch (std::exception& e)
catch (const std::exception& e)
{
Log(Debug::Error) << "Failed to update LuaManager: " << e.what();
}
mUpdateRequest = false;
mUpdateRequest.reset();
lk.unlock();
mCV.notify_one();
}

View File

@ -1,14 +1,17 @@
#ifndef OPENMW_MWLUA_WORKER_H
#define OPENMW_MWLUA_WORKER_H
#include <osg/Timer>
#include <osg/ref_ptr>
#include <condition_variable>
#include <mutex>
#include <optional>
#include <thread>
namespace osgViewer
namespace osg
{
class Viewer;
class Stats;
}
namespace MWLua
@ -18,26 +21,32 @@ namespace MWLua
class Worker
{
public:
explicit Worker(LuaManager& manager, osgViewer::Viewer& viewer);
explicit Worker(LuaManager& manager);
~Worker();
void allowUpdate();
void allowUpdate(osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats);
void finishUpdate();
void finishUpdate(osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats);
void join();
private:
void update();
struct UpdateRequest
{
osg::Timer_t mFrameStart;
unsigned mFrameNumber;
osg::ref_ptr<osg::Stats> mStats;
};
void update(osg::Timer_t frameStart, unsigned frameNumber, osg::Stats& stats);
void run() noexcept;
LuaManager& mManager;
osgViewer::Viewer& mViewer;
std::mutex mMutex;
std::condition_variable mCV;
bool mUpdateRequest = false;
std::optional<UpdateRequest> mUpdateRequest;
bool mJoinRequest = false;
std::optional<std::thread> mThread;
};