Merge branch 'fix_osg_stats_report' into 'master'

Report osg stats for frames with loading screens (#7737)

Closes #7737

See merge request OpenMW/openmw!4053
pull/3235/head
psi29a 8 months ago
commit 5b25435260

@ -145,6 +145,7 @@
Bug #7723: Assaulting vampires and werewolves shouldn't be a crime Bug #7723: Assaulting vampires and werewolves shouldn't be a crime
Bug #7724: Guards don't help vs werewolves Bug #7724: Guards don't help vs werewolves
Bug #7733: Launcher shows incorrect data paths when there's two plugins with the same name Bug #7733: Launcher shows incorrect data paths when there's two plugins with the same name
Bug #7737: OSG stats are missing some data on loading screens
Bug #7742: Governing attribute training limit should use the modified attribute Bug #7742: Governing attribute training limit should use the modified attribute
Bug #7753: Editor: Actors Don't Scale According to Their Race Bug #7753: Editor: Actors Don't Scale According to Their Race
Bug #7758: Water walking is not taken into account to compute path cost on the water Bug #7758: Water walking is not taken into account to compute path cost on the water

@ -165,6 +165,15 @@ namespace
private: private:
int mMaxTextureImageUnits = 0; int mMaxTextureImageUnits = 0;
}; };
void reportStats(unsigned frameNumber, osgViewer::Viewer& viewer, std::ostream& stream)
{
viewer.getViewerStats()->report(stream, frameNumber);
osgViewer::Viewer::Cameras cameras;
viewer.getCameras(cameras);
for (osg::Camera* camera : cameras)
camera->getStats()->report(stream, frameNumber);
}
} }
void OMW::Engine::executeLocalScripts() void OMW::Engine::executeLocalScripts()
@ -180,10 +189,9 @@ void OMW::Engine::executeLocalScripts()
} }
} }
bool OMW::Engine::frame(float frametime) bool OMW::Engine::frame(unsigned frameNumber, float frametime)
{ {
const osg::Timer_t frameStart = mViewer->getStartTick(); const osg::Timer_t frameStart = mViewer->getStartTick();
const unsigned int frameNumber = mViewer->getFrameStamp()->getFrameNumber();
const osg::Timer* const timer = osg::Timer::instance(); const osg::Timer* const timer = osg::Timer::instance();
osg::Stats* const stats = mViewer->getViewerStats(); osg::Stats* const stats = mViewer->getViewerStats();
@ -340,11 +348,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 +919,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.
@ -1020,7 +1029,9 @@ void OMW::Engine::go()
mViewer->advance(timeManager.getRenderingSimulationTime()); mViewer->advance(timeManager.getRenderingSimulationTime());
if (!frame(dt)) const unsigned frameNumber = mViewer->getFrameStamp()->getFrameNumber();
if (!frame(frameNumber, dt))
{ {
std::this_thread::sleep_for(std::chrono::milliseconds(5)); std::this_thread::sleep_for(std::chrono::milliseconds(5));
continue; continue;
@ -1034,16 +1045,16 @@ void OMW::Engine::go()
if (stats) if (stats)
{ {
// The delay is required because rendering happens in parallel to the main thread and stats from there is
// available with delay.
constexpr unsigned statsReportDelay = 3; constexpr unsigned statsReportDelay = 3;
const auto frameNumber = mViewer->getFrameStamp()->getFrameNumber();
if (frameNumber >= statsReportDelay) if (frameNumber >= statsReportDelay)
{ {
const unsigned reportFrameNumber = frameNumber - statsReportDelay; // Viewer frame number can be different from frameNumber because of loading screens which render new
mViewer->getViewerStats()->report(stats, reportFrameNumber); // frames inside a simulation frame.
osgViewer::Viewer::Cameras cameras; const unsigned currentFrameNumber = mViewer->getFrameStamp()->getFrameNumber();
mViewer->getCameras(cameras); for (unsigned i = frameNumber; i <= currentFrameNumber; ++i)
for (auto camera : cameras) reportStats(i - statsReportDelay, *mViewer, stats);
camera->getStats()->report(stats, reportFrameNumber);
} }
} }

@ -188,7 +188,7 @@ namespace OMW
void executeLocalScripts(); void executeLocalScripts();
bool frame(float dt); bool frame(unsigned frameNumber, float dt);
/// Prepare engine for game play /// Prepare engine for game play
void prepareEngine(); void prepareEngine();

@ -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();
} }

@ -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;
}; };

Loading…
Cancel
Save