From a5de07c03b10141f0cb707e611152c69ffdc34e1 Mon Sep 17 00:00:00 2001 From: Quentin Bazin Date: Thu, 10 Jun 2021 15:05:55 +0200 Subject: [PATCH] [ClientProfilerWindow] Added. --- CMakeLists.txt | 1 + external/gamekit | 2 +- source/client/core/ClientApplication.cpp | 47 +++++++ source/client/core/ClientApplication.hpp | 7 + source/client/core/ClientProfiler.cpp | 15 +- source/client/core/ClientProfiler.hpp | 32 ++++- source/client/core/Config.cpp | 3 + source/client/core/Config.hpp | 1 + source/client/hud/DebugProfilerWindow.cpp | 117 ++++++++++++++++ source/client/hud/DebugProfilerWindow.hpp | 156 +++++++++++++++++++++ source/client/hud/HUD.cpp | 16 +++ source/client/hud/HUD.hpp | 3 + source/client/states/SettingsMenuState.cpp | 1 + source/client/world/ChunkMeshBuilder.cpp | 5 + source/client/world/ClientWorld.cpp | 9 ++ 15 files changed, 404 insertions(+), 11 deletions(-) create mode 100644 source/client/hud/DebugProfilerWindow.cpp create mode 100644 source/client/hud/DebugProfilerWindow.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index adc34ea85..91be33c78 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,7 @@ set(DEBUG_GCC_FLAGS -Wall -Wextra -Wconversion -Wno-unused-parameter -Wfatal-errors -DGK_DEBUG + -DOM_PROFILER_ENABLED ) set(RELEASE_GCC_FLAGS diff --git a/external/gamekit b/external/gamekit index d770f4892..388f8d9de 160000 --- a/external/gamekit +++ b/external/gamekit @@ -1 +1 @@ -Subproject commit d770f48928abaacd23f186c307a865688d7edb50 +Subproject commit 388f8d9de2868b3bd6ad3657093fdf00420e5dcf diff --git a/source/client/core/ClientApplication.cpp b/source/client/core/ClientApplication.cpp index ffaabb627..d71fcf654 100644 --- a/source/client/core/ClientApplication.cpp +++ b/source/client/core/ClientApplication.cpp @@ -118,6 +118,10 @@ bool ClientApplication::init() { m_resourceHandler.add("font-ascii", "texture-font", "resources/textures/font.properties"); m_resourceHandler.add("atlas-blocks"); +#ifdef OM_PROFILER_ENABLED + ClientProfiler::setInstance(&m_profiler); +#endif + auto &titleScreen = m_stateStack.push(m_port); if (m_argumentParser.getArgument("singleplayer").isFound) titleScreen.startSingleplayer(false); @@ -128,6 +132,8 @@ bool ClientApplication::init() { } void ClientApplication::handleEvents() { + OM_PROFILE_START("OS events"); + gk::CoreApplication::handleEvents(); if ((Config::isFullscreenModeEnabled && m_window.getWindowMode() != gk::Window::Mode::Fullscreen) @@ -141,6 +147,8 @@ void ClientApplication::handleEvents() { if (Config::isVerticalSyncEnabled != m_window.isVerticalSyncEnabled()) m_window.setVerticalSyncEnabled(Config::isVerticalSyncEnabled); + + OM_PROFILE_END("OS events"); } void ClientApplication::onEvent(const SDL_Event &event) { @@ -156,6 +164,45 @@ void ClientApplication::onExit() { m_keyboardHandler.saveKeysToFile("config/keys.lua"); } +void ClientApplication::mainLoop() { + m_clock.startFpsTimer(); + + // FIXME: The window should probably be closed after the main loop ends + while(m_window.isOpen() && !m_stateStack.empty() && !hasBeenInterrupted) { + OM_PROFILE_BEGIN_TICK(); + + handleEvents(); + + m_eventHandler.processEvents(); + + m_clock.updateGame([&] { + OM_PROFILE_START("Update"); + + if (!m_stateStack.empty()) + m_stateStack.top().update(); + + m_stateStack.clearDeletedStates(); + + OM_PROFILE_END("Update"); + }); + + m_clock.drawGame([&] { + m_window.clear(); + + OM_PROFILE_START("Draw"); + + if(!m_stateStack.empty()) + m_window.draw(m_stateStack.top(), m_renderStates); + + OM_PROFILE_END("Draw"); + + m_window.display(); + }); + + OM_PROFILE_END_TICK(); + } +} + void ClientApplication::initOpenGL() { // Enable textures glCheck(glEnable(GL_TEXTURE_2D)); diff --git a/source/client/core/ClientApplication.hpp b/source/client/core/ClientApplication.hpp index 8d0868d19..906b1e018 100644 --- a/source/client/core/ClientApplication.hpp +++ b/source/client/core/ClientApplication.hpp @@ -29,6 +29,7 @@ #include +#include "ClientProfiler.hpp" #include "KeyboardHandler.hpp" class ClientApplication : public gk::CoreApplication { @@ -43,12 +44,18 @@ class ClientApplication : public gk::CoreApplication { void onEvent(const SDL_Event &event) override; void onExit() override; + void mainLoop() override; + static void initOpenGL(); KeyboardHandler m_keyboardHandler; std::string m_host = "localhost"; u16 m_port = 4242; + +#ifdef OM_PROFILER_ENABLED + ClientProfiler m_profiler; +#endif }; #endif // CLIENTAPPLICATION_HPP_ diff --git a/source/client/core/ClientProfiler.cpp b/source/client/core/ClientProfiler.cpp index 02e20b7c2..5368bdce1 100644 --- a/source/client/core/ClientProfiler.cpp +++ b/source/client/core/ClientProfiler.cpp @@ -29,24 +29,27 @@ #include "ClientProfiler.hpp" +u64 ClientProfiler::tickCount = 0; + ClientProfiler *ClientProfiler::s_instance = nullptr; void ClientProfiler::onBeginTick() { m_ticks.emplace_back(); - m_ticks.back().begin = gk::GameClock::getInstance().getTicks(true); + m_ticks.back().begin = std::chrono::system_clock::now(); } void ClientProfiler::onEndTick() { - m_ticks.back().end = gk::GameClock::getInstance().getTicks(true); + m_ticks.back().end = std::chrono::system_clock::now(); + ++tickCount; } void ClientProfiler::startAction(const std::string &name) { m_ticks.back().actions[name].durations.emplace_back(); - m_ticks.back().actions[name].durations.back().first = gk::GameClock::getInstance().getTicks(true); + m_ticks.back().actions[name].durations.back().first = std::chrono::system_clock::now(); } void ClientProfiler::endAction(const std::string &name) { - m_ticks.back().actions[name].durations.back().second = gk::GameClock::getInstance().getTicks(true); + m_ticks.back().actions[name].durations.back().second = std::chrono::system_clock::now(); } void ClientProfiler::dump(u64 tickDurationMin) { @@ -54,7 +57,7 @@ void ClientProfiler::dump(u64 tickDurationMin) { u64 i = 0; for (auto &tick : m_ticks) { - u64 tickDuration = tick.end - tick.begin; + u64 tickDuration = std::chrono::duration_cast(tick.end - tick.begin).count(); if (tickDuration < tickDurationMin) continue; gkDebug() << "Tick" << i++ << "took" << tickDuration << "ms"; @@ -63,7 +66,7 @@ void ClientProfiler::dump(u64 tickDurationMin) { for (auto &[actionName, action] : tick.actions) { u64 j = 0; for (auto &[begin, end] : action.durations) { - u64 actionDuration = end - begin; + u64 actionDuration = std::chrono::duration_cast(end - begin).count(); if (maxActionDuration.find(actionName) == maxActionDuration.end()) maxActionDuration.emplace(actionName, std::make_pair(actionDuration, 0)); diff --git a/source/client/core/ClientProfiler.hpp b/source/client/core/ClientProfiler.hpp index c8026364a..2a3374cee 100644 --- a/source/client/core/ClientProfiler.hpp +++ b/source/client/core/ClientProfiler.hpp @@ -27,19 +27,36 @@ #ifndef CLIENTPROFILER_HPP_ #define CLIENTPROFILER_HPP_ +#include #include #include #include #include +#ifdef OM_PROFILER_ENABLED +# define OM_PROFILE_START(name) ClientProfiler::getInstance().startAction(name); +# define OM_PROFILE_END(name) ClientProfiler::getInstance().endAction(name); + +# define OM_PROFILE_BEGIN_TICK() ClientProfiler::getInstance().onBeginTick(); +# define OM_PROFILE_END_TICK() ClientProfiler::getInstance().onEndTick(); +#else +# define OM_PROFILE_START(name) {} +# define OM_PROFILE_END(name) {} + +# define OM_PROFILE_BEGIN_TICK() {} +# define OM_PROFILE_END_TICK() {} +#endif + +using TimePoint = std::chrono::time_point; + struct ClientAction { - std::deque> durations; + std::deque> durations; }; struct ClientTick { - u64 begin; - u64 end; + TimePoint begin; + TimePoint end; std::unordered_map actions; }; @@ -53,13 +70,20 @@ class ClientProfiler { void startAction(const std::string &name); void endAction(const std::string &name); + // FIXME: m_ticks.size() - 1 is actually the current tick + const ClientTick &getLastTick() const { return m_ticks.at(m_ticks.size() - 2); }; + + std::size_t getTickCount() const { return m_ticks.size(); } + static ClientProfiler &getInstance() { return *s_instance; } static void setInstance(ClientProfiler *instance) { s_instance = instance; } + static u64 tickCount; + private: static ClientProfiler *s_instance; - std::deque m_ticks; + std::deque m_ticks; // TODO: Use a std::vector }; #endif // CLIENTPROFILER_HPP_ diff --git a/source/client/core/Config.cpp b/source/client/core/Config.cpp index 53ba2f762..9c5811d0b 100644 --- a/source/client/core/Config.cpp +++ b/source/client/core/Config.cpp @@ -69,6 +69,7 @@ u8 Config::mouseSensitivity = 8; // Debug bool Config::isChunkMinimapEnabled = false; bool Config::isLightmapViewerEnabled = false; +bool Config::isProfilerWindowEnabled = false; // Other std::string Config::defaultUsername = ""; @@ -114,6 +115,7 @@ void Config::loadConfigFromFile(const char *filename) { isChunkMinimapEnabled = lua["isChunkMinimapEnabled"].get_or(isChunkMinimapEnabled); isLightmapViewerEnabled = lua["isLightmapViewerEnabled"].get_or(isLightmapViewerEnabled); + isProfilerWindowEnabled = lua["isProfilerWindowEnabled"].get_or(isProfilerWindowEnabled); defaultUsername = lua["defaultUsername"].get_or(defaultUsername); defaultServerAddress = lua["defaultServerAddress"].get_or(defaultServerAddress); @@ -156,6 +158,7 @@ void Config::saveConfigToFile(const char *filename) { file << std::endl; file << "isChunkMinimapEnabled = " << (isChunkMinimapEnabled ? "true" : "false") << std::endl; file << "isLightmapViewerEnabled = " << (isLightmapViewerEnabled ? "true" : "false") << std::endl; + file << "isProfilerWindowEnabled = " << (isProfilerWindowEnabled ? "true" : "false") << std::endl; file << std::endl; file << "defaultUsername = \"" << defaultUsername << "\"" << std::endl; file << "defaultServerAddress = \"" << defaultServerAddress << "\"" << std::endl; diff --git a/source/client/core/Config.hpp b/source/client/core/Config.hpp index 4cc26f0fd..8dc9117ea 100644 --- a/source/client/core/Config.hpp +++ b/source/client/core/Config.hpp @@ -64,6 +64,7 @@ namespace Config { // Debug extern bool isChunkMinimapEnabled; extern bool isLightmapViewerEnabled; + extern bool isProfilerWindowEnabled; // Other extern std::string defaultUsername; diff --git a/source/client/hud/DebugProfilerWindow.cpp b/source/client/hud/DebugProfilerWindow.cpp new file mode 100644 index 000000000..a706cc748 --- /dev/null +++ b/source/client/hud/DebugProfilerWindow.cpp @@ -0,0 +1,117 @@ +/* + * ===================================================================================== + * + * OpenMiner + * + * Copyright (C) 2018-2020 Unarelith, Quentin Bazin + * Copyright (C) 2019-2020 the OpenMiner contributors (see CONTRIBUTORS.md) + * + * This file is part of OpenMiner. + * + * OpenMiner is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * OpenMiner is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OpenMiner; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * ===================================================================================== + */ +#include +#include + +#include "DebugProfilerWindow.hpp" + +DebugProfilerWindow::DebugProfilerWindow() { +#ifndef OM_PROFILER_ENABLED + m_text.setString("Profiler disabled.\nPlease recompile with -DOM_PROFILER_ENABLED to enable it."); +#endif +} + +void DebugProfilerWindow::onEvent(const SDL_Event &event) { + if (event.type == SDL_KEYDOWN) { + switch (event.key.keysym.sym) { + case SDLK_a: m_mode = DebugProfilerWindowMode::Total; break; + case SDLK_p: m_mode = DebugProfilerWindowMode::Prev; break; + case SDLK_s: m_mode = DebugProfilerWindowMode::Min; break; + case SDLK_l: m_mode = DebugProfilerWindowMode::Max; break; + } + } +} + +void DebugProfilerWindow::update() { +#ifdef OM_PROFILER_ENABLED + ClientProfiler &profiler = ClientProfiler::getInstance(); + std::size_t ticks = profiler.getTickCount(); + + // FIXME: Some information may be lost here + const ClientTick &tick = profiler.getLastTick(); + if (&tick == m_lastTick) return; + m_lastTick = &tick; + + m_snapshot.addTick(tick); + + constexpr std::size_t updateDisplayFrequency = 60; + if (ticks - m_lastUpdate >= updateDisplayFrequency) { + m_lastUpdate = ticks; + + std::stringstream stream; + stream << "In the last " << updateDisplayFrequency << " ticks:\n"; + stream << "Tick count: " << m_snapshot.tickCount() << "\n"; + stream << "- [A] Total: " << (float)m_snapshot.totalTicksDuration() / 1000.f << " ms (" + << (float)m_snapshot.totalTicksDuration() / 1000.0f / updateDisplayFrequency << " ms/t)\n"; + + stream << "- [P] Prev: " << (float)m_snapshot.previousTickDuration() / 1000.f << " ms\n"; + stream << "- [S] Min: " << (float)m_snapshot.shortestPreviousTickDuration() / 1000.f << " ms\n"; + stream << "- [L] Max: " << (float)m_snapshot.longestPreviousTickDuration() / 1000.f << " ms\n"; + + if (m_mode == DebugProfilerWindowMode::Total) + stream << "Total actions during those ticks:\n"; + else if (m_mode == DebugProfilerWindowMode::Prev) + stream << "Actions for last tick:\n"; + else if (m_mode == DebugProfilerWindowMode::Min) + stream << "Actions for shortest tick since last update:\n"; + else if (m_mode == DebugProfilerWindowMode::Max) + stream << "Actions for longest tick since last update:\n"; + + std::map> snapshotData; + for (auto &[valueName, value] : m_snapshot.values()) { + if (value.hasDataForTick(&tick) || m_mode == DebugProfilerWindowMode::Total) { + std::pair pair{valueName, value}; + if (m_mode == DebugProfilerWindowMode::Total) + snapshotData.emplace(value.totalTime(nullptr), pair); + else + snapshotData.emplace(value.totalTime(&tick), pair); + } + } + + for (auto &[displayedValue, value] : snapshotData) { + stream << "- " << value.first << " ("; + if (m_mode == DebugProfilerWindowMode::Total) + stream << value.second.wholeSnapshotCallCount(); + else + stream << value.second.lastTickCallCount(); + stream << "): " << (float)displayedValue / 1000.f << " ms (" + << (float)value.second.totalTime(nullptr) / 1000.f / updateDisplayFrequency << " ms/t)\n"; + } + + m_text.setString(stream.str()); + + m_snapshot.reset(); + } +#endif +} + +void DebugProfilerWindow::draw(gk::RenderTarget &target, gk::RenderStates states) const { + states.transform *= getTransform(); + + target.draw(m_text, states); +} + diff --git a/source/client/hud/DebugProfilerWindow.hpp b/source/client/hud/DebugProfilerWindow.hpp new file mode 100644 index 000000000..23e93dd27 --- /dev/null +++ b/source/client/hud/DebugProfilerWindow.hpp @@ -0,0 +1,156 @@ +/* + * ===================================================================================== + * + * OpenMiner + * + * Copyright (C) 2018-2020 Unarelith, Quentin Bazin + * Copyright (C) 2019-2020 the OpenMiner contributors (see CONTRIBUTORS.md) + * + * This file is part of OpenMiner. + * + * OpenMiner is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * OpenMiner is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OpenMiner; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * ===================================================================================== + */ +#ifndef DEBUGPROFILERWINDOW_HPP_ +#define DEBUGPROFILERWINDOW_HPP_ + +#include +#include + +#include + +#include "ClientProfiler.hpp" +#include "Text.hpp" + +enum class DebugProfilerWindowMode { + Total, + Prev, + Min, + Max +}; + +class DebugProfilerSnapshotValue { + public: + void addDuration(const ClientTick *tick, const TimePoint &start, const TimePoint &end) { + m_lastValue = std::chrono::duration_cast(end - start).count(); + m_totalTime += m_lastValue; + + m_minValue = std::min(m_minValue, m_lastValue); + m_maxValue = std::max(m_maxValue, m_lastValue); + + m_values[tick].emplace_back(m_lastValue); + m_lastTick = tick; + } + + void clear() { + m_lastValue = 0; + m_totalTime = 0; + + m_minValue = std::numeric_limits::max(); + m_maxValue = std::numeric_limits::min(); + + m_lastTick = nullptr; + m_values.clear(); + } + + bool hasDataForTick(const ClientTick *tick) const { return m_values.find(tick) != m_values.end(); } + + u64 lastValue() const { return m_lastValue; } + u64 totalTime(const ClientTick *tick) const { + if (tick) { + u64 sum = 0; + for (auto &it : m_values.at(tick)) + sum += it; + return sum; + } + + return m_totalTime; + } + + u64 minValue() const { return m_minValue; } + u64 maxValue() const { return m_maxValue; } + + u64 lastTickCallCount() const { return m_lastTick ? m_values.at(m_lastTick).size() : 0; } + u64 wholeSnapshotCallCount() const { + u64 total = 0; + for (auto &it : m_values) + total += it.second.size(); + return total; + } + + private: + u64 m_lastValue = 0; + u64 m_totalTime = 0; + + u64 m_minValue = std::numeric_limits::max(); + u64 m_maxValue = std::numeric_limits::min(); + + const ClientTick *m_lastTick = nullptr; + std::unordered_map> m_values; +}; + +class DebugProfilerSnapshot { + public: + void reset() { + m_tickDuration.clear(); + m_values.clear(); + } + + void addTick(const ClientTick &tick) { + m_tickDuration.addDuration(&tick, tick.begin, tick.end); + + for (auto &[actionName, action] : tick.actions) + for (auto &[start, end] : action.durations) + m_values[actionName].addDuration(&tick, start, end); + } + + const std::unordered_map &values() const { return m_values; } + + u64 tickCount() const { return m_tickDuration.wholeSnapshotCallCount(); } + u64 totalTicksDuration() const { return m_tickDuration.totalTime(nullptr); } + u64 previousTickDuration() const { return m_tickDuration.lastValue(); } + u64 shortestPreviousTickDuration() const { return m_tickDuration.minValue(); } + u64 longestPreviousTickDuration() const { return m_tickDuration.maxValue(); } + + private: + DebugProfilerSnapshotValue m_tickDuration; + + std::unordered_map m_values; +}; + +class DebugProfilerWindow : public gk::Transformable, public gk::Drawable { + public: + DebugProfilerWindow(); + + void onEvent(const SDL_Event &event); + + void update(); + + private: + void draw(gk::RenderTarget &target, gk::RenderStates states) const override; + + Text m_text; + + std::size_t m_lastUpdate = 0; + + DebugProfilerWindowMode m_mode = DebugProfilerWindowMode::Prev; + + DebugProfilerSnapshot m_snapshot; + + const ClientTick *m_lastTick = nullptr; +}; + +#endif // DEBUGPROFILERWINDOW_HPP_ diff --git a/source/client/hud/HUD.cpp b/source/client/hud/HUD.cpp index e5ebf017c..9d5ad7d01 100644 --- a/source/client/hud/HUD.cpp +++ b/source/client/hud/HUD.cpp @@ -30,6 +30,7 @@ #include "ClientCommandHandler.hpp" #include "ClientPlayer.hpp" +#include "ClientProfiler.hpp" #include "Config.hpp" #include "Events.hpp" #include "HUD.hpp" @@ -71,6 +72,8 @@ void HUD::setup() { m_minimap.setPosition(float(Config::screenWidth / Config::guiScale - Minimap::minimapSize) - 15.f, 15.f); m_debugLightmapViewer.setPosition(0.f, float(Config::screenHeight / Config::guiScale - DebugLightmapViewer::totalSize)); + + m_debugProfilerWindow.setPosition(2.f, 2.f); } void HUD::onEvent(const SDL_Event &event) { @@ -86,6 +89,9 @@ void HUD::onEvent(const SDL_Event &event) { if (Config::isChunkMinimapEnabled) m_minimap.onEvent(event); + + if (Config::isProfilerWindowEnabled) + m_debugProfilerWindow.onEvent(event); } void HUD::onGuiScaleChanged(const GuiScaleChangedEvent &event) { @@ -119,9 +125,14 @@ void HUD::update() { if (Config::isLightmapViewerEnabled) m_debugLightmapViewer.update(m_world); + + if (Config::isProfilerWindowEnabled) + m_debugProfilerWindow.update(); } void HUD::draw(gk::RenderTarget &target, gk::RenderStates states) const { + OM_PROFILE_START("HUD::draw"); + target.disableView(); states.shader = &m_shader; @@ -148,11 +159,16 @@ void HUD::draw(gk::RenderTarget &target, gk::RenderStates states) const { if (Config::isLightmapViewerEnabled) target.draw(m_debugLightmapViewer, states); + if (Config::isProfilerWindowEnabled) + target.draw(m_debugProfilerWindow, states); + target.draw(m_chat, states); states.transform = gk::Transform::Identity; if (Config::isCrosshairVisible) target.draw(m_crosshair, states); + + OM_PROFILE_END("HUD::draw"); } diff --git a/source/client/hud/HUD.hpp b/source/client/hud/HUD.hpp index 58491bb4a..8ec9caa83 100644 --- a/source/client/hud/HUD.hpp +++ b/source/client/hud/HUD.hpp @@ -35,6 +35,7 @@ #include "Crosshair.hpp" #include "DebugLightmapViewer.hpp" #include "DebugOverlay.hpp" +#include "DebugProfilerWindow.hpp" #include "Hotbar.hpp" #include "Minimap.hpp" @@ -86,6 +87,8 @@ class HUD : public gk::Transformable, public gk::Drawable { Minimap m_minimap; DebugLightmapViewer m_debugLightmapViewer; + + DebugProfilerWindow m_debugProfilerWindow; }; #endif // HUD_HPP_ diff --git a/source/client/states/SettingsMenuState.cpp b/source/client/states/SettingsMenuState.cpp index 7015c1fe9..4f9e8fb50 100644 --- a/source/client/states/SettingsMenuState.cpp +++ b/source/client/states/SettingsMenuState.cpp @@ -329,6 +329,7 @@ void SettingsMenuState::addDebugButtons() { addToggleButton("Show chunk minimap", Config::isChunkMinimapEnabled, false); addToggleButton("Show lightmap viewer", Config::isLightmapViewerEnabled, false); + addToggleButton("Show profiler window", Config::isProfilerWindowEnabled, false); updateWidgetPosition(); } diff --git a/source/client/world/ChunkMeshBuilder.cpp b/source/client/world/ChunkMeshBuilder.cpp index 510d36482..7d96d453f 100644 --- a/source/client/world/ChunkMeshBuilder.cpp +++ b/source/client/world/ChunkMeshBuilder.cpp @@ -26,6 +26,7 @@ */ #include "BlockGeometry.hpp" #include "ChunkMeshBuilder.hpp" +#include "ClientProfiler.hpp" #include "ClientWorld.hpp" #include "TextureAtlas.hpp" @@ -40,6 +41,8 @@ using namespace BlockGeometry; // so if it changes during the execution, that would cause problems there too. // void ChunkMeshBuilder::addMeshBuildingJob(const Chunk &chunk, const TextureAtlas &textureAtlas) { + OM_PROFILE_START("ChunkMeshBuilder::addMeshBuildingJob"); + // Creating the job (creates a copy of the chunk to send it to the thread) ChunkMeshBuildingJob job; job.textureAtlas = &textureAtlas; @@ -69,6 +72,8 @@ void ChunkMeshBuilder::addMeshBuildingJob(const Chunk &chunk, const TextureAtlas }, job); m_futures.emplace_back(std::move(future)); + + OM_PROFILE_END("ChunkMeshBuilder::addMeshBuildingJob"); } void ChunkMeshBuilder::update() { diff --git a/source/client/world/ClientWorld.cpp b/source/client/world/ClientWorld.cpp index 3d6078694..70ef32c9d 100644 --- a/source/client/world/ClientWorld.cpp +++ b/source/client/world/ClientWorld.cpp @@ -33,6 +33,7 @@ #include "ClientCommandHandler.hpp" #include "ClientPlayer.hpp" +#include "ClientProfiler.hpp" #include "ClientWorld.hpp" #include "Events.hpp" #include "Registry.hpp" @@ -125,6 +126,8 @@ void ClientWorld::changeDimension(u16 dimensionID) { void ClientWorld::receiveChunkData(Network::Packet &packet) { if (!m_dimension) return; + OM_PROFILE_START("ClientWorld::receiveChunkData"); + s32 cx, cy, cz; packet >> cx >> cy >> cz; @@ -189,6 +192,8 @@ void ClientWorld::receiveChunkData(Network::Packet &packet) { m_eventHandler->emplaceEvent(gk::Vector3i{cx, cy, cz}, true); // gkDebug() << "Chunk at" << cx << cy << cz << "received"; + + OM_PROFILE_END("ClientWorld::receiveChunkData"); } void ClientWorld::removeChunk(const gk::Vector3i &chunkPos) { @@ -257,6 +262,8 @@ void ClientWorld::draw(gk::RenderTarget &target, gk::RenderStates states) const return; } + OM_PROFILE_START("ClientWorld::draw"); + states.vertexAttributes = VertexAttribute::All; gk::Shader::bind(states.shader); @@ -353,5 +360,7 @@ void ClientWorld::draw(gk::RenderTarget &target, gk::RenderStates states) const states.transform = gk::Transform::Identity; target.draw(m_scene, states); + + OM_PROFILE_END("ClientWorld::draw"); }