mirror of
https://github.com/rwengine/openrw.git
synced 2024-11-25 11:52:40 +01:00
Use microprofile for profiling
This commit is contained in:
parent
63a2caa471
commit
080a0fe050
@ -2,73 +2,22 @@
|
||||
#define _RWENGINE_PROFILER_HPP_
|
||||
|
||||
#ifdef RW_PROFILER
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#define time_unit std::chrono::microseconds
|
||||
|
||||
#include <rw/debug.hpp>
|
||||
|
||||
namespace perf {
|
||||
|
||||
struct ProfileEntry {
|
||||
std::string label;
|
||||
int64_t start;
|
||||
int64_t end;
|
||||
std::vector<ProfileEntry> childProfiles;
|
||||
};
|
||||
|
||||
class Profiler {
|
||||
ProfileEntry frame;
|
||||
std::chrono::high_resolution_clock::time_point frameBegin;
|
||||
std::stack<ProfileEntry> currentStack;
|
||||
|
||||
public:
|
||||
static Profiler& get() {
|
||||
static Profiler profile;
|
||||
return profile;
|
||||
}
|
||||
|
||||
const ProfileEntry& getFrame() const {
|
||||
return frame;
|
||||
}
|
||||
|
||||
void startFrame() {
|
||||
frameBegin = std::chrono::high_resolution_clock::now();
|
||||
frame = {"Frame", 0, 0, {}};
|
||||
}
|
||||
|
||||
void beginEvent(const std::string& label) {
|
||||
auto now = std::chrono::duration_cast<time_unit>(
|
||||
std::chrono::high_resolution_clock::now() - frameBegin);
|
||||
currentStack.push({label, now.count(), 0, {}});
|
||||
}
|
||||
|
||||
void endEvent() {
|
||||
auto now = std::chrono::duration_cast<time_unit>(
|
||||
std::chrono::high_resolution_clock::now() - frameBegin);
|
||||
RW_CHECK(currentStack.size() > 0, "Perf stack is empty");
|
||||
currentStack.top().end = now.count();
|
||||
if (currentStack.size() == 1) {
|
||||
frame.childProfiles.push_back(currentStack.top());
|
||||
currentStack.pop();
|
||||
} else {
|
||||
auto tmp = currentStack.top();
|
||||
currentStack.pop();
|
||||
currentStack.top().childProfiles.push_back(std::move(tmp));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
#define RW_PROFILE_FRAME_BOUNDARY() perf::Profiler::get().startFrame();
|
||||
#define RW_PROFILE_BEGIN(label) perf::Profiler::get().beginEvent(label);
|
||||
#define RW_PROFILE_END() perf::Profiler::get().endEvent();
|
||||
#include <microprofile.h>
|
||||
#define RW_PROFILE_THREAD(name) MicroProfileOnThreadCreate(name)
|
||||
#define RW_PROFILE_FRAME_BOUNDARY() MicroProfileFlip(nullptr)
|
||||
#define RW_PROFILE_SCOPE(label) MICROPROFILE_SCOPEI("Default", label, MP_YELLOW)
|
||||
#define RW_PROFILE_COUNTER_ADD(name, qty) MICROPROFILE_COUNTER_ADD(name, qty)
|
||||
#define RW_PROFILE_COUNTER_SET(name, qty) MICROPROFILE_COUNTER_SET(name, qty)
|
||||
#define RW_TIMELINE_ENTER(name, color) MICROPROFILE_TIMELINE_ENTER_STATIC(color, name)
|
||||
#define RW_TIMELINE_LEAVE(name) MICROPROFILE_TIMELINE_LEAVE_STATIC(name)
|
||||
#else
|
||||
#define RW_PROFILE_FRAME_BOUNDARY()
|
||||
#define RW_PROFILE_BEGIN(label)
|
||||
#define RW_PROFILE_END()
|
||||
#define RW_PROFILE_THREAD(name) do {} while (0)
|
||||
#define RW_PROFILE_FRAME_BOUNDARY() do {} while (0)
|
||||
#define RW_PROFILE_SCOPE(label) do {} while (0)
|
||||
#define RW_PROFILE_COUNTER_ADD(name, qty) do {} while (0)
|
||||
#define RW_PROFILE_COUNTER_SET(name, qty) do {} while (0)
|
||||
#define RW_TIMELINE_ENTER(name, color) do {} while (0)
|
||||
#define RW_TIMELINE_LEAVE(name) do {} while (0)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <rw/types.hpp>
|
||||
|
||||
#include "core/Logger.hpp"
|
||||
#include "core/Profiler.hpp"
|
||||
#include "engine/GameState.hpp"
|
||||
#include "engine/GameWorld.hpp"
|
||||
#include "loaders/LoaderCOL.hpp"
|
||||
@ -349,6 +350,7 @@ void GameData::loadWater(const std::string& path) {
|
||||
}
|
||||
|
||||
void GameData::loadTXD(const std::string& name) {
|
||||
RW_PROFILE_COUNTER_ADD("loadTXD", 1);
|
||||
auto slot = name;
|
||||
auto ext = name.find(".txd");
|
||||
if (ext != std::string::npos) {
|
||||
@ -368,6 +370,7 @@ void GameData::loadTXD(const std::string& name) {
|
||||
}
|
||||
|
||||
TextureArchive GameData::loadTextureArchive(const std::string& name) {
|
||||
RW_PROFILE_COUNTER_ADD("loadTextureArchive", 1);
|
||||
/// @todo refactor loadTXD to use correct file locations
|
||||
auto file = index.openFile(name);
|
||||
if (!file.data) {
|
||||
|
@ -306,9 +306,9 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera& camera,
|
||||
}
|
||||
|
||||
void GameRenderer::renderObjects(const GameWorld *world) {
|
||||
renderer->useProgram(worldProg.get());
|
||||
RW_PROFILE_SCOPE(__func__);
|
||||
|
||||
RW_PROFILE_BEGIN("RenderList");
|
||||
renderer->useProgram(worldProg.get());
|
||||
|
||||
// This is sequential at the moment, it should be easy to make it
|
||||
// run in parallel with a good threading system.
|
||||
@ -316,8 +316,6 @@ void GameRenderer::renderObjects(const GameWorld *world) {
|
||||
// Naive optimisation, assume 50% hitrate
|
||||
renderList.reserve(world->allObjects.size() * 0.5f);
|
||||
|
||||
RW_PROFILE_BEGIN("Build");
|
||||
|
||||
ObjectRenderer objectRenderer(_renderWorld,
|
||||
(cullOverride ? cullingCamera : _camera),
|
||||
_renderAlpha, getMissingTexture());
|
||||
@ -366,12 +364,10 @@ void GameRenderer::renderObjects(const GameWorld *world) {
|
||||
objectRenderer.renderClump(arrowModel.get(), model, nullptr, renderList);
|
||||
}
|
||||
|
||||
RW_PROFILE_END();
|
||||
culled += objectRenderer.culled;
|
||||
renderer->pushDebugGroup("Objects");
|
||||
renderer->pushDebugGroup("RenderList");
|
||||
// Also parallelizable
|
||||
RW_PROFILE_BEGIN("Sort");
|
||||
// Earlier position in the array means earlier object's rendering
|
||||
// Transparent objects should be sorted and rendered after opaque
|
||||
sort(renderList.begin(), renderList.end(),
|
||||
@ -383,15 +379,10 @@ void GameRenderer::renderObjects(const GameWorld *world) {
|
||||
return false;
|
||||
return (a.sortKey > b.sortKey);
|
||||
});
|
||||
RW_PROFILE_END();
|
||||
RW_PROFILE_BEGIN("Draw");
|
||||
renderer->drawBatched(renderList);
|
||||
RW_PROFILE_END();
|
||||
|
||||
renderer->popDebugGroup();
|
||||
profObjects = renderer->popDebugGroup();
|
||||
|
||||
RW_PROFILE_END();
|
||||
}
|
||||
|
||||
void GameRenderer::renderSplash(GameWorld* world, GLuint splashTexName, glm::u16vec3 fc) {
|
||||
|
@ -45,6 +45,9 @@ RWGame::RWGame(Logger& log, int argc, char* argv[])
|
||||
: GameBase(log, argc, argv)
|
||||
, data(&log, config.getGameDataPath())
|
||||
, renderer(&log, &data) {
|
||||
RW_PROFILE_THREAD("Main");
|
||||
RW_TIMELINE_ENTER("Startup", MP_YELLOW);
|
||||
|
||||
bool newgame = options.count("newgame");
|
||||
bool test = options.count("test");
|
||||
std::string startSave(
|
||||
@ -106,6 +109,7 @@ RWGame::RWGame(Logger& log, int argc, char* argv[])
|
||||
});
|
||||
|
||||
log.info("Game", "Started");
|
||||
RW_TIMELINE_LEAVE("Startup");
|
||||
}
|
||||
|
||||
RWGame::~RWGame() {
|
||||
@ -401,38 +405,31 @@ int RWGame::run() {
|
||||
}
|
||||
|
||||
float RWGame::tickWorld(const float deltaTime, float accumulatedTime) {
|
||||
RW_PROFILE_SCOPE(__func__);
|
||||
auto deltaTimeWithTimeScale =
|
||||
deltaTime * world->state->basic.timeScale;
|
||||
|
||||
RW_PROFILE_BEGIN("Update");
|
||||
while (accumulatedTime >= deltaTime) {
|
||||
if (!StateManager::currentState()) {
|
||||
break;
|
||||
}
|
||||
|
||||
RW_PROFILE_BEGIN("physics");
|
||||
world->dynamicsWorld->stepSimulation(
|
||||
deltaTimeWithTimeScale, kMaxPhysicsSubSteps, deltaTime);
|
||||
RW_PROFILE_END();
|
||||
|
||||
RW_PROFILE_BEGIN("state");
|
||||
StateManager::get().tick(deltaTimeWithTimeScale);
|
||||
RW_PROFILE_END();
|
||||
|
||||
RW_PROFILE_BEGIN("engine");
|
||||
tick(deltaTimeWithTimeScale);
|
||||
RW_PROFILE_END();
|
||||
|
||||
getState()->swapInputState();
|
||||
|
||||
accumulatedTime -= deltaTime;
|
||||
}
|
||||
RW_PROFILE_END();
|
||||
return accumulatedTime;
|
||||
}
|
||||
|
||||
bool RWGame::updateInput() {
|
||||
RW_PROFILE_BEGIN("Input");
|
||||
RW_PROFILE_SCOPE(__func__);
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
switch (event.type) {
|
||||
@ -463,17 +460,16 @@ bool RWGame::updateInput() {
|
||||
|
||||
GameInput::updateGameInputState(&getState()->input[0], event);
|
||||
|
||||
RW_PROFILE_BEGIN("State");
|
||||
if (StateManager::currentState()) {
|
||||
RW_PROFILE_SCOPE("State");
|
||||
StateManager::currentState()->handleEvent(event);
|
||||
}
|
||||
RW_PROFILE_END()
|
||||
}
|
||||
RW_PROFILE_END();
|
||||
return true;
|
||||
}
|
||||
|
||||
void RWGame::tick(float dt) {
|
||||
RW_PROFILE_SCOPE(__func__);
|
||||
State* currState = StateManager::get().states.back().get();
|
||||
|
||||
static float clockAccumulator = 0.f;
|
||||
@ -569,8 +565,7 @@ void RWGame::tick(float dt) {
|
||||
}
|
||||
|
||||
void RWGame::render(float alpha, float time) {
|
||||
RW_PROFILE_BEGIN("Render");
|
||||
RW_PROFILE_BEGIN("engine");
|
||||
RW_PROFILE_SCOPE(__func__);
|
||||
|
||||
lastDraws = getRenderer().getRenderer()->getDrawCount();
|
||||
|
||||
@ -600,29 +595,22 @@ void RWGame::render(float alpha, float time) {
|
||||
|
||||
renderer.getRenderer()->pushDebugGroup("World");
|
||||
|
||||
RW_PROFILE_BEGIN("world");
|
||||
renderer.renderWorld(world.get(), viewCam, alpha);
|
||||
RW_PROFILE_END();
|
||||
|
||||
renderer.getRenderer()->popDebugGroup();
|
||||
|
||||
renderDebugView(time, viewCam);
|
||||
|
||||
if (!world->isPaused()) drawOnScreenText(world.get(), &renderer);
|
||||
RW_PROFILE_END();
|
||||
|
||||
RW_PROFILE_BEGIN("state");
|
||||
if (StateManager::currentState()) {
|
||||
RW_PROFILE_SCOPE("state");
|
||||
StateManager::get().draw(&renderer);
|
||||
}
|
||||
RW_PROFILE_END();
|
||||
RW_PROFILE_END();
|
||||
|
||||
renderProfile();
|
||||
}
|
||||
|
||||
void RWGame::renderDebugView(float time, ViewCamera &viewCam) {
|
||||
RW_PROFILE_BEGIN("debug");
|
||||
RW_PROFILE_SCOPE(__func__);
|
||||
switch (debugview_) {
|
||||
case DebugViewMode::General:
|
||||
renderDebugStats(time);
|
||||
@ -640,7 +628,6 @@ void RWGame::renderDebugView(float time, ViewCamera &viewCam) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
RW_PROFILE_END();
|
||||
}
|
||||
|
||||
void RWGame::renderDebugStats(float time) {
|
||||
@ -851,55 +838,6 @@ void RWGame::renderDebugObjects(float time, ViewCamera& camera) {
|
||||
}
|
||||
}
|
||||
|
||||
void RWGame::renderProfile() {
|
||||
#ifdef RW_PROFILER
|
||||
auto& frame = perf::Profiler::get().getFrame();
|
||||
constexpr float upperlimit = 30000.f;
|
||||
constexpr float lineHeight = 15.f;
|
||||
static std::vector<glm::vec4> perf_colours;
|
||||
if (perf_colours.size() == 0) {
|
||||
float c = 8.f;
|
||||
for (int r = 0; r < c; ++r) {
|
||||
for (int g = 0; g < c; ++g) {
|
||||
for (int b = 0; b < c; ++b) {
|
||||
perf_colours.emplace_back(r / c, g / c, b / c, 1.f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float xscale = renderer.getRenderer()->getViewport().x / upperlimit;
|
||||
TextRenderer::TextInfo ti;
|
||||
ti.align = TextRenderer::TextInfo::TextAlignment::Left;
|
||||
ti.font = FONT_ARIAL;
|
||||
ti.size = lineHeight - 2.f;
|
||||
ti.baseColour = glm::u8vec3(255);
|
||||
std::function<void(const perf::ProfileEntry&, int)> renderEntry =
|
||||
[&](const perf::ProfileEntry& entry, int depth) {
|
||||
int g = 0;
|
||||
for (auto& event : entry.childProfiles) {
|
||||
auto duration = event.end - event.start;
|
||||
float y = 60.f + (depth * (lineHeight + 5.f));
|
||||
renderer.drawColour(
|
||||
perf_colours[(std::hash<std::string>()(entry.label) *
|
||||
(g++)) %
|
||||
perf_colours.size()],
|
||||
{xscale * event.start, y, xscale * duration, lineHeight});
|
||||
ti.screenPosition.x = xscale * (event.start);
|
||||
ti.screenPosition.y = y + 2.f;
|
||||
ti.text = GameStringUtil::fromString(
|
||||
event.label + " " + std::to_string(duration) + " us ", ti.font);
|
||||
renderer.text.renderText(ti);
|
||||
renderEntry(event, depth + 1);
|
||||
}
|
||||
};
|
||||
renderEntry(frame, 0);
|
||||
ti.screenPosition = glm::vec2(xscale * (16000), 40.f);
|
||||
ti.text = GameStringUtil::fromString(".16 ms", ti.font);
|
||||
renderer.text.renderText(ti);
|
||||
#endif
|
||||
}
|
||||
|
||||
void RWGame::globalKeyEvent(const SDL_Event& event) {
|
||||
const auto toggle_debug = [&](DebugViewMode m) {
|
||||
debugview_ = debugview_ == m ? DebugViewMode::Disabled : m;
|
||||
|
@ -127,7 +127,6 @@ private:
|
||||
void renderDebugStats(float time);
|
||||
void renderDebugPaths(float time);
|
||||
void renderDebugObjects(float time, ViewCamera& camera);
|
||||
void renderProfile();
|
||||
|
||||
void handleCheatInput(char symbol);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user