Skip to content

Commit

Permalink
Merge branch 'fix_osg_stats_report' into 'master'
Browse files Browse the repository at this point in the history
Report osg stats for frames with loading screens (#7737)

Closes #7737

See merge request OpenMW/openmw!4053
  • Loading branch information
psi29a committed Apr 28, 2024
2 parents 1e1fd28 + 41d5d3b commit 5b25435
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 39 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@
Bug #7723: Assaulting vampires and werewolves shouldn't be a crime
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 #7737: OSG stats are missing some data on loading screens
Bug #7742: Governing attribute training limit should use the modified attribute
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
Expand Down
37 changes: 24 additions & 13 deletions apps/openmw/engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,15 @@ namespace
private:
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()
Expand All @@ -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 unsigned int frameNumber = mViewer->getFrameStamp()->getFrameNumber();
const osg::Timer* const timer = osg::Timer::instance();
osg::Stats* const stats = mViewer->getViewerStats();

Expand Down Expand Up @@ -340,11 +348,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;
}
Expand Down Expand Up @@ -910,7 +919,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.
Expand Down Expand Up @@ -1020,7 +1029,9 @@ void OMW::Engine::go()

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));
continue;
Expand All @@ -1034,16 +1045,16 @@ void OMW::Engine::go()

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;
const auto frameNumber = mViewer->getFrameStamp()->getFrameNumber();
if (frameNumber >= statsReportDelay)
{
const unsigned reportFrameNumber = frameNumber - statsReportDelay;
mViewer->getViewerStats()->report(stats, reportFrameNumber);
osgViewer::Viewer::Cameras cameras;
mViewer->getCameras(cameras);
for (auto camera : cameras)
camera->getStats()->report(stats, reportFrameNumber);
// Viewer frame number can be different from frameNumber because of loading screens which render new
// frames inside a simulation frame.
const unsigned currentFrameNumber = mViewer->getFrameStamp()->getFrameNumber();
for (unsigned i = frameNumber; i <= currentFrameNumber; ++i)
reportStats(i - statsReportDelay, *mViewer, stats);
}
}

Expand Down
2 changes: 1 addition & 1 deletion apps/openmw/engine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ namespace OMW

void executeLocalScripts();

bool frame(float dt);
bool frame(unsigned frameNumber, float dt);

/// Prepare engine for game play
void prepareEngine();
Expand Down
33 changes: 16 additions & 17 deletions apps/openmw/mwlua/worker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(); });
Expand All @@ -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()
Expand All @@ -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();
}
Expand All @@ -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();
}
Expand Down
25 changes: 17 additions & 8 deletions apps/openmw/mwlua/worker.hpp
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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;
};
Expand Down

0 comments on commit 5b25435

Please sign in to comment.