< 2021SC@SDUSC OvGame of open source game engine Overload code module analysis -- DebugFrameInfo & GameProfiler

2021SC@SDUSC
OvGame (V) - Debug (Part 2) frameinfo & gameprofiler

preface

This is the next installment of OvGame's Debug. We will explore its last two parts, frameinfo & gameprofiler. To learn about another part of Debug, go to Debug (Part 1) read.

In addition, if you want to get a general understanding of the major modules of the engine, you can go to the author This related article see.
If you want to know the OvGame outline, you can go to the author This article.

analysis

1,FrameInfo

1.1 FrameInfo.h

1.1.1 header file

#include <OvRendering/Core/Renderer.h>
#include <OvWindowing/Window.h>

#include <OvUI/Panels/PanelUndecorated.h>
#include <OvUI/Widgets/Texts/TextColored.h>

The header files of this file are from other modules of Overload and will not be described in detail.

1.1.2 main codes

The main code of this file is the FrameInfo class, which can generate the display panel of Frame Information. It is defined as follows:

	class FrameInfo : public OvUI::Panels::PanelUndecorated
	{
	public:
		/**
		* Constructor
		* @param p_renderer
		* @param p_window
		*/
		FrameInfo(OvRendering::Core::Renderer& p_renderer, OvWindowing::Window& p_window);

		/**
		* Update the data
		* @parma p_deltaTime
		*/
		void Update(float p_deltaTime);

	private:
		OvRendering::Core::Renderer&	m_renderer;
		OvWindowing::Window&			m_window;

		OvUI::Widgets::Texts::TextColored* m_frameInfo[3];
	};

Obviously, like the class explored in the previous article, this class inherits the paneluncorrected class of OvUI. Please go to for details Utils (final) outline and fpscounter & debug (first) outline and DriverInfo see. In addition, the functions defined in this class have been annotated, so I won't say more; The defined variables are renderer class, window class and colored text class array.

1.2 FrameInfo.cpp

This file only contains the FrameInfo.h header file above, so look directly at the function:

FrameInfo() function

OvGame::Debug::FrameInfo::FrameInfo(OvRendering::Core::Renderer& p_renderer, OvWindowing::Window& p_window) :
	m_renderer(p_renderer),
	m_window(p_window)
{
	m_defaultHorizontalAlignment = OvUI::Settings::EHorizontalAlignment::LEFT;
	m_defaultVerticalAlignment = OvUI::Settings::EVerticalAlignment::BOTTOM;
	m_defaultPosition.x = static_cast<float>(p_window.GetSize().first) - 10.f;
	m_defaultPosition.y = static_cast<float>(p_window.GetSize().second) - 10.f;

	m_frameInfo[0] = &CreateWidget<OvUI::Widgets::Texts::TextColored>("", OvUI::Types::Color::Yellow);
	m_frameInfo[1] = &CreateWidget<OvUI::Widgets::Texts::TextColored>("", OvUI::Types::Color::Yellow);
	m_frameInfo[2] = &CreateWidget<OvUI::Widgets::Texts::TextColored>("", OvUI::Types::Color::Yellow);
}

This is the constructor of class. First, use the parameter initialization table to assign values to the renderer and window; Secondly, as in the previous article, the format alignment enumeration class is used as the variable m of the parent APanelTransformable class_ Defaulthorizontalalignment and m_defaultVerticalAlignment assignment to realize left alignment and bottom alignment; Next, it is also the variable m of its parent class APanelTransformable_ Defaultposition, in M_ GetSize() of window obtains the window width and height, and sets the default position of the panel.

Finally, for the class array M_ The three objects of frameinfo are assigned values, and the CreateWidget() function is used, which is in Utils (final) outline and fpscounter & debug (first) outline and DriverInfo It has also been resolved. Please go to check it yourself.

Update() function

void OvGame::Debug::FrameInfo::Update(float p_deltaTime)
{
	auto& frameInfo = m_renderer.GetFrameInfo();

	m_frameInfo[0]->content = "Triangles: " + std::to_string(frameInfo.polyCount);
	m_frameInfo[1]->content = "Batches: " + std::to_string(frameInfo.batchCount);
	m_frameInfo[2]->content = "Instances: " + std::to_string(frameInfo.instanceCount);

	SetPosition({ 10.0f , static_cast<float>(m_window.GetSize().second) - 10.f });
	SetAlignment(OvUI::Settings::EHorizontalAlignment::LEFT, OvUI::Settings::EVerticalAlignment::BOTTOM);
}

First, GetFrameInfo() returns the FrameInfo of the Renderer class of OvRendering::Core, and assigns the FrameInfo of auto & (self determination type); Then, M_ The string variable content of FrameInfo assigns the number of triangles, the number of batches and the number of instances respectively, where the data is the data directly read from the structure FrameInfo; Then, the SetPosition() function of the APanelTransformable parent class is called to set the initial position of the panel. Finally, pass the left alignment and bottom alignment into the function SetAlignment() of apaneltransformable class to set the alignment format.

2,GameProfiler

2.1 GameProfiler.h

2.1.1 header file

#include <OvRendering/Core/Renderer.h>
#include <OvWindowing/Window.h>

#include <OvAnalytics/Profiling/Profiler.h>
#include <OvUI/Panels/PanelUndecorated.h>
#include <OvUI/Widgets/Texts/TextColored.h>
#include <OvUI/Widgets/Layout/Group.h>
#include <OvUI/Widgets/Buttons/Button.h>

The header files of this file are from other modules of Overload and will not be described in detail.

2.1.2 main codes

The main code is the GameProfiler class, which can generate the panel of profiling information and configuration file information. The definition is quite long. Let's first look at the function definition, as follows:

class GameProfiler : public OvUI::Panels::PanelUndecorated
	{
	public:
		/**
		* Constructor
		* @param p_window
		* @param p_frequency
		*/
		GameProfiler(OvWindowing::Window& p_window, float p_frequency);

		/**
		* Update the data
		* @param p_deltaTime
		*/
		void Update(float p_deltaTime);

	private:
		OvUI::Types::Color CalculateActionColor(double p_percentage) const;
		std::string GenerateActionString(OvAnalytics::Profiling::ProfilerReport::Action& p_action);

This class includes two public functions and two private functions. The public functions are annotated. I won't say more; Private functions are specifically defined in GameProfiler.cpp and will not be described temporarily.

	private:

		float m_frequency;
		float m_timer = 0.f;

		OvAnalytics::Profiling::Profiler m_profiler;

		OvWindowing::Window& m_window;
		OvUI::Widgets::AWidget* m_separator;
		OvUI::Widgets::Texts::TextColored* m_elapsedFramesText;
		OvUI::Widgets::Texts::TextColored* m_elapsedTimeText;
		OvUI::Widgets::Layout::Group* m_actionList;
	};

This class declares multiple private variables, which is known in most previous articles. Where, m_frequency is used to record the time period; m_timer is used to record the accumulated elapsed time; Profiler is a configuration file class that collects relevant data of running programs; Window is a window class; AWidget is a component class; TextColored is a colored text class; Group is a widget class that can contain other widgets.

2.2 GameProfiler.cpp

2.2.1 header file

This file also introduces more header files of other Overload modules, which will not be described in detail for the time being:

#include "OvGame/Debug/GameProfiler.h"

#include <OvDebug/Utils/Logger.h>
#include <OvUI/Widgets/Visual/Separator.h>
#include <OvAnalytics/Profiling/ProfilerSpy.h>

2.2.2 main codes

Before the function, the following namespaces are added to make the code concise:

using namespace OvUI::Panels;
using namespace OvUI::Widgets;
using namespace OvUI::Types;

Now, let's first understand the two private functions, which are very simple and will not be described too much:

CalculateActionColor() function
OvUI::Types::Color OvGame::Debug::GameProfiler::CalculateActionColor(double p_percentage) const
{
	if (p_percentage <= 25.0f)		return { 0.0f, 1.0f, 0.0f, 1.0f };
	else if (p_percentage <= 50.0f) return { 1.0f, 1.0f, 0.0f, 1.0f };
	else if (p_percentage <= 75.0f) return { 1.0f, 0.6f, 0.0f, 1.0f };
	else							return { 1.0f, 0.0f, 0.0f, 1.0f };
}

This function is responsible for calculating the Color of the operation. The type is Color structure Color. Obviously, the parameter passed in means the percentage of operation completion, which will affect the returned Color data.

GenerateActionString() function
std::string OvGame::Debug::GameProfiler::GenerateActionString(OvAnalytics::Profiling::ProfilerReport::Action & p_action)
{
	std::string result;

	result += "[" + p_action.name + "]";
	result += std::to_string(p_action.duration) + "s (total) | ";
	result += std::to_string(p_action.duration / p_action.calls) + "s (per call) | ";
	result += std::to_string(p_action.percentage) + "%% | ";
	result += std::to_string(p_action.calls) + " calls";

	return result;
}

The type of this function is string, and the structure ProfilerReport is passed in, which means the operation of the called method; The returned string information is the combination of name, duration and other information in the structure.

In brief, there are also functions with the same name and code as the above two functions in the OvEditor::Panels::Profiler class, which can not be confused.

Next, continue to learn about public functions:

GameProfiler() function
OvGame::Debug::GameProfiler::GameProfiler(OvWindowing::Window& p_window, float p_frequency) : m_frequency(p_frequency), m_window(p_window)
{
	m_defaultHorizontalAlignment = OvUI::Settings::EHorizontalAlignment::LEFT;
	m_defaultPosition = { 10.0f, 10.0f };

	CreateWidget<Texts::Text>("Profiler state: ").lineBreak = true;

	m_elapsedFramesText = &CreateWidget<Texts::TextColored>("", Color(1.f, 0.8f, 0.01f, 1));
	m_elapsedTimeText = &CreateWidget<Texts::TextColored>("", Color(1.f, 0.8f, 0.01f, 1));
	m_separator = &CreateWidget<OvUI::Widgets::Visual::Separator>();
	m_actionList = &CreateWidget<Layout::Group>();

	m_actionList->CreateWidget<Texts::Text>("Action | Total duration | Frame Duration | Frame load | Total calls");

	m_profiler.Enable();

	m_elapsedFramesText->enabled = true;
	m_elapsedTimeText->enabled = true;
	m_separator->enabled = true;
}

The function is a constructor. Firstly, the parameter initialization table initializes the frequency and window; Then, as above, set the left alignment and the default position of the panel, the CreateWidget() function creates a text panel to display the file data, and set lineBreak = true, that is, line breaks are allowed; Then, set four private variables with CreateWidget(); Then, M_ After assignment, actionlist calls CreateWidget() to set the text, which corresponds to the ProfilerReport structure mentioned above; Finally, set the activation of the parts set in the above column in turn, so that they can be drawn.

Update() function

This function is relatively long. Let's explore it paragraph by paragraph:

void OvGame::Debug::GameProfiler::Update(float p_deltaTime)
{
	PROFILER_SPY("Game Profiler Update");

	m_position = { 10.0f, static_cast<float>(m_window.GetSize().second / 2) };

	m_timer += p_deltaTime;

First, use PROFILER_SPY, author Previous articles As already mentioned, here is the profile update; Then set the panel position and time.

Next, judge M_ Whether the profiler is activated (as mentioned in the constructor):

	if (m_profiler.IsEnabled())
	{
		m_profiler.Update(p_deltaTime);

After passing, call oviditor:: Core:: Editor:: update() to update a series of updates, including global shortcut keys, current editor mode, etc; Then, judge that if the recorded time exceeds the set cycle time, enter the while cycle:

		while (m_timer >= m_frequency)
		{			
			OvAnalytics::Profiling::ProfilerReport report = m_profiler.GenerateReport();
			m_profiler.ClearHistory();
			m_actionList->RemoveAllWidgets();

			m_elapsedFramesText->content = "Elapsed frames: " + std::to_string(report.elapsedFrames);
			m_elapsedTimeText->content = "Elapsed time: " + std::to_string(report.elaspedTime);

			m_actionList->CreateWidget<Texts::Text>("Action | Total duration | Frame Duration | Frame load | Total calls");

First, M_ The profiler calls GenerateReport() to return the HardwareReport structure containing hardware information, and then M_ The profiler calls ClearHistory() to clear all records of collected data, and the operation list m_actionList calls RemoveAllWidgets() to remove all components; Then, like the constructor, set the two text and the text of the operation list; Then, without exiting the while loop, continue to enter the following for loop:

			for (auto& action : report.actions)
			{
				auto color = CalculateActionColor(action.percentage);
				m_actionList->CreateWidget<Texts::TextColored>(GenerateActionString(action), color);
			}
		
			m_timer -= m_frequency;
		}
	}
}

The length of the loop depends on the vector container actions of the report. In the loop, operate on the members of actions in turn: first call CalculateActionColor() above to get the color corresponding to the progress of the operation, and then CreateWidget() to create colored text. The content is the string of the operation information converted by GenerateActionString() above.

After all action s are operated, exit the for loop and m_timer deduct the time of this cycle; If m after deduction_ When timer is less than the unit cycle time, exit the while loop and end the function.

summary

This article parses the last two parts of OvGame's Debug, and all the contents of the Debug file are parsed. Generally speaking, Debug is a display operation of some information, which is not complex.

Now that we have learned about the Utils and Debug files of OvGame, we can continue to change the subsequent contents of the Core file. Therefore, in the next article, we can continue to understand the Game part of OvGame's Core file.

Keywords: C++

Added by jera on Wed, 08 Dec 2021 20:56:20 +0200