1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-03-25 16:43:33 +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(); 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(); mViewer->renderingTraversals();
mLuaWorker->finishUpdate(); mLuaWorker->finishUpdate(frameStart, frameNumber, *stats);
return true; return true;
} }
@ -910,7 +911,7 @@ void OMW::Engine::prepareEngine()
mLuaManager->init(); mLuaManager->init();
// starts a separate lua thread if "lua num threads" > 0 // 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. // Initialise and enter main loop.

View File

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

View File

@ -1,14 +1,17 @@
#ifndef OPENMW_MWLUA_WORKER_H #ifndef OPENMW_MWLUA_WORKER_H
#define OPENMW_MWLUA_WORKER_H #define OPENMW_MWLUA_WORKER_H
#include <osg/Timer>
#include <osg/ref_ptr>
#include <condition_variable> #include <condition_variable>
#include <mutex> #include <mutex>
#include <optional> #include <optional>
#include <thread> #include <thread>
namespace osgViewer namespace osg
{ {
class Viewer; class Stats;
} }
namespace MWLua namespace MWLua
@ -18,26 +21,32 @@ namespace MWLua
class Worker class Worker
{ {
public: public:
explicit Worker(LuaManager& manager, osgViewer::Viewer& viewer); explicit Worker(LuaManager& manager);
~Worker(); ~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(); void join();
private: 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; void run() noexcept;
LuaManager& mManager; LuaManager& mManager;
osgViewer::Viewer& mViewer;
std::mutex mMutex; std::mutex mMutex;
std::condition_variable mCV; std::condition_variable mCV;
bool mUpdateRequest = false; std::optional<UpdateRequest> mUpdateRequest;
bool mJoinRequest = false; bool mJoinRequest = false;
std::optional<std::thread> mThread; std::optional<std::thread> mThread;
}; };