add visualization of cpu time usage (set SHOW_DEBUG_INFO = true)

master
Vectozavr 2021-11-03 15:19:01 +07:00
parent 5b8698af03
commit a8fafbdaec
10 changed files with 199 additions and 13 deletions

View File

@ -91,7 +91,7 @@ add_executable(shooter
engine/network/UDPConnection.h
engine/network/UDPSocket.cpp
engine/network/UDPSocket.h
engine/SoundController.cpp engine/SoundController.h ShooterMsgType.h ShooterMsgType.cpp engine/animation/AAttractToPoint.h engine/animation/ARotateRelativePoint.h engine/animation/ARotateLeft.h)
engine/SoundController.cpp engine/SoundController.h ShooterMsgType.h ShooterMsgType.cpp engine/animation/AAttractToPoint.h engine/animation/ARotateRelativePoint.h engine/animation/ARotateLeft.h engine/utils/Timer.cpp engine/utils/Timer.h)
if(APPLE OR UNIX)
include_directories(/usr/local/include)

View File

@ -16,7 +16,7 @@ namespace Consts {
const std::string PROJECT_NAME = "engine";
const bool USE_LOG_FILE = true;
const bool USE_OPEN_GL = true;
const bool SHOW_DEBUG_INFO = false;
const bool SHOW_DEBUG_INFO = true;
const bool SHOW_FPS_COUNTER = true;
const double PI = 3.14159265358979323846264338327950288;

View File

@ -30,20 +30,32 @@ void Engine::create(int screenWidth, int screenHeight, const std::string &name,
camera->init(screenWidth, screenHeight);
while (screen->isOpen()) {
// 'd' in the beginning of the name means debug.
// While printing debug info we will take into account only timer names witch start with 'd '
Time::startTimer("d all");
screen->clear();
Time::update();
Time::startTimer("d game update");
update();
Time::stopTimer("d game update");
// sometimes we dont need to update physics world
// (for example in menu or while pause)
// hence we can set '_updateWorld' equal to false in setUpdateWorld(bool):
if (_updateWorld) {
Time::startTimer("d animations");
Timeline::update();
Time::stopTimer("d animations");
Time::startTimer("d collisions");
world->update();
Time::stopTimer("d collisions");
Time::startTimer("d projections");
if (_useOpenGL) {
GLfloat *view = camera->glView();
for (auto &it : *world) {
@ -70,17 +82,21 @@ void Engine::create(int screenWidth, int screenHeight, const std::string &name,
_triPerSec = camera->buffSize() * Time::fps();
}
Time::stopTimer("d projections");
if (Consts::SHOW_FPS_COUNTER) {
screen->drawText(std::to_string(Time::fps()) + " fps", Vec2D(static_cast<double>(screen->width()) - 100.0, 10.0), 25,
screen->drawText(std::to_string(Time::fps()) + " fps",
Vec2D(static_cast<double>(screen->width()) - 100.0, 10.0), 25,
sf::Color(100, 100, 100));
}
printDebugText();
printDebugInfo();
gui();
}
screen->display();
Time::stopTimer("d all");
}
}
@ -97,9 +113,10 @@ void Engine::exit() {
std::to_string(screen->height()) + ") with title '" + screen->title() + "'.");
}
void Engine::printDebugText() const {
void Engine::printDebugInfo() const {
if (_debugText) {
if (_showDebugInfo) {
// coordinates & fps:
std::string text = _name + "\n\n X: " +
std::to_string((camera->position().x())) + "\n Y: " +
std::to_string((camera->position().y())) + "\n Z: " +
@ -110,7 +127,7 @@ void Engine::printDebugText() const {
if (_useOpenGL) {
text += "\n Using OpenGL acceleration";
} else {
text += "\n" + std::to_string( _triPerSec) + " tris/s";
text += "\n" + std::to_string(_triPerSec) + " tris/s";
}
sf::Text t;
@ -122,5 +139,54 @@ void Engine::printDebugText() const {
t.setPosition(static_cast<float>(screen->width()) - 400.0f, 10.0f);
screen->drawText(t);
// timers:
int timerWidth = screen->width() - 100;
float xPos = 50;
float yPos = 300;
int height = 50;
double totalTime = Time::elapsedTimerMilliseconds("d all");
double timeSum = 0;
int i = 0;
for (auto &[timerName, timer] : Time::timers()) {
int width = timerWidth * timer.elapsedMilliseconds() / totalTime;
if (timerName == "d all" || timerName[0] != 'd') {
continue;
}
screen->drawTetragon(Vec2D{xPos, yPos + height * i},
Vec2D{xPos + width, yPos + height * i},
Vec2D{xPos + width, yPos + height + height * i},
Vec2D{xPos, yPos + height + height * i},
{static_cast<sf::Uint8>(255 * width / timerWidth),
static_cast<sf::Uint8>(255 * (1 - width / timerWidth)),
0, 100});
screen->drawText(
timerName.substr(2, timerName.size()) + " (" + std::to_string((int) (100 * timer.elapsedMilliseconds() / totalTime)) + "%)",
Vec2D{xPos + 10, yPos + height * i + 5}, 30,
sf::Color(0, 0, 0, 100));
i++;
timeSum += timer.elapsedMilliseconds();
}
int width = timerWidth * (totalTime - timeSum) / totalTime;
screen->drawTetragon(Vec2D{xPos, yPos + height * i},
Vec2D{xPos + width, yPos + height * i},
Vec2D{xPos + width, yPos + height + height * i},
Vec2D{xPos, yPos + height + height * i},
{static_cast<sf::Uint8>(255 * width / timerWidth),
static_cast<sf::Uint8>(255 * (1 - width / timerWidth)),
0, 100});
screen->drawText("other (" + std::to_string((int) (100 * (totalTime - timeSum) / totalTime)) + "%)",
Vec2D{xPos + 10, yPos + height * i + 5}, 30,
sf::Color(0, 0, 0, 100));
}
}

View File

@ -18,10 +18,10 @@ private:
int _triPerSec = 0;
bool _updateWorld = true;
bool _debugText = Consts::SHOW_DEBUG_INFO;
bool _showDebugInfo = Consts::SHOW_DEBUG_INFO;
bool _useOpenGL = Consts::USE_OPEN_GL;
void printDebugText() const;
void printDebugInfo() const;
protected:
const std::shared_ptr<Screen> screen = std::make_shared<Screen>();
@ -35,7 +35,7 @@ protected:
virtual void update() {};
void setDebugText(bool value) { _debugText = value; }
void setDebugText(bool value) { _showDebugInfo = value; }
void setUpdateWorld(bool value) { _updateWorld = value; }

View File

@ -70,6 +70,44 @@ int Time::fps() {
return static_cast<int>(_instance->_lastFps);
}
void Time::startTimer(const std::string &timerName) {
if (!_validInstance) {
return;
}
_instance->_timers.insert({timerName, Timer()});
_instance->_timers[timerName].start();
}
void Time::stopTimer(const std::string &timerName) {
if (!_validInstance) {
return;
}
if(_instance->_timers.count(timerName) > 0) {
_instance->_timers[timerName].stop();
}
}
double Time::elapsedTimerMilliseconds(const std::string &timerName) {
if (!_validInstance) {
return 0;
}
if(_instance->_timers.count(timerName) > 0) {
return _instance->_timers[timerName].elapsedMilliseconds();
}
return 0;
}
double Time::elapsedTimerSeconds(const std::string &timerName) {
if (!_validInstance) {
return 0;
}
if(_instance->_timers.count(timerName) > 0) {
return _instance->_timers[timerName].elapsedSeconds();
}
return 0;
}
void Time::free() {
_validInstance = false;
delete _instance;

View File

@ -6,9 +6,14 @@
#define ENGINE_TIME_H
#include <chrono>
#include <map>
#include "Timer.h"
class Time final {
private:
std::map<std::string, Timer> _timers;
// High precision time
std::chrono::high_resolution_clock::time_point _start = std::chrono::high_resolution_clock::now();
std::chrono::high_resolution_clock::time_point _last = _start;
@ -44,6 +49,14 @@ public:
static void init();
static void free();
static void startTimer(const std::string& timerName);
static void stopTimer(const std::string& timerName);
[[nodiscard]] static double elapsedTimerMilliseconds(const std::string& timerName);
[[nodiscard]] static double elapsedTimerSeconds(const std::string& timerName);
[[nodiscard]] static std::map<std::string, Timer> const & timers() { return _instance->_timers; }
};
#endif //INC_3DZAVR_TIME_H

33
engine/utils/Timer.cpp Normal file
View File

@ -0,0 +1,33 @@
//
// Created by Иван Ильин on 03.11.2021.
//
#include "Timer.h"
using namespace std::chrono;
void Timer::start() {
_startTime = high_resolution_clock::now();
_isRunning = true;
}
void Timer::stop() {
_endTime = high_resolution_clock::now();
_isRunning = false;
}
double Timer::elapsedMilliseconds() const {
high_resolution_clock::time_point endTime;
if(_isRunning) {
endTime = high_resolution_clock::now();
} else {
endTime = _endTime;
}
return duration<double>(endTime - _startTime).count();
}
double Timer::elapsedSeconds() const {
return elapsedMilliseconds() / 1000.0;
}

28
engine/utils/Timer.h Normal file
View File

@ -0,0 +1,28 @@
//
// Created by Иван Ильин on 03.11.2021.
//
#ifndef SHOOTER_TIMER_H
#define SHOOTER_TIMER_H
#include <iostream>
#include <chrono>
#include <ctime>
#include <cmath>
class Timer {
private:
std::chrono::high_resolution_clock::time_point _startTime;
std::chrono::high_resolution_clock::time_point _endTime;
bool _isRunning = false;
public:
void start();
void stop();
[[nodiscard]] double elapsedMilliseconds() const;
[[nodiscard]] double elapsedSeconds() const;
};
#endif //SHOOTER_TIMER_H

View File

@ -184,6 +184,7 @@
<ClCompile Include="engine\Triangle.cpp" />
<ClCompile Include="engine\utils\Log.cpp" />
<ClCompile Include="engine\utils\Time.cpp" />
<ClInclude Include="engine\utils\Timer.cpp" />
<ClCompile Include="engine\Vec2D.cpp" />
<ClCompile Include="engine\Vec3D.cpp" />
<ClCompile Include="engine\Vec4D.cpp" />
@ -236,6 +237,7 @@
<ClInclude Include="engine\Triangle.h" />
<ClInclude Include="engine\utils\Log.h" />
<ClInclude Include="engine\utils\Time.h" />
<ClInclude Include="engine\utils\Timer.h" />
<ClInclude Include="engine\Vec2D.h" />
<ClInclude Include="engine\Vec3D.h" />
<ClInclude Include="engine\Vec4D.h" />

View File

@ -105,6 +105,12 @@
<ClCompile Include="engine\utils\Log.cpp">
<Filter>Исходные файлы\engine\utils</Filter>
</ClCompile>
<ClCompile Include="engine\utils\Time.cpp">
<Filter>Исходные файлы\engine\utils</Filter>
</ClCompile>
<ClCompile Include="engine\utils\Timer.cpp">
<Filter>Исходные файлы\engine\utils</Filter>
</ClCompile>
<ClCompile Include="engine\Matrix4x4.cpp">
<Filter>Исходные файлы\engine</Filter>
</ClCompile>
@ -141,9 +147,6 @@
<ClCompile Include="engine\SoundController.cpp">
<Filter>Исходные файлы\engine</Filter>
</ClCompile>
<ClCompile Include="engine\utils\Time.cpp">
<Filter>Исходные файлы\engine\utils</Filter>
</ClCompile>
<ClCompile Include="engine\Triangle.cpp">
<Filter>Исходные файлы\engine</Filter>
</ClCompile>
@ -323,6 +326,9 @@
<ClInclude Include="engine\utils\Time.h">
<Filter>Файлы заголовков\engine\utils</Filter>
</ClInclude>
<ClInclude Include="engine\utils\Timer.h">
<Filter>Файлы заголовков\engine\utils</Filter>
</ClInclude>
<ClInclude Include="engine\physics\Simplex.h">
<Filter>Файлы заголовков\engine\physics</Filter>
</ClInclude>