Created
October 8, 2025 10:43
-
-
Save vittorioromeo/71aba1be2c30a75ffc8147184650ea90 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
// LICENSE AND COPYRIGHT (C) INFORMATION | |
// https://github.com/vittorioromeo/VRSFML/blob/master/license.md | |
//////////////////////////////////////////////////////////// | |
// Headers | |
//////////////////////////////////////////////////////////// | |
#include "SFML/System/Clock.hpp" | |
#include "SFML/System/Time.hpp" | |
#include "SFML/Base/Assert.hpp" | |
#include "SFML/Base/IntTypes.hpp" | |
#include "SFML/Base/SizeT.hpp" | |
#include "SFML/Base/Span.hpp" | |
#include "SFML/Base/StringView.hpp" | |
namespace sfex | |
{ | |
//////////////////////////////////////////////////////////// | |
struct [[nodiscard]] ScopeInfo | |
{ | |
sf::base::StringView label; | |
sf::base::StringView file; | |
sf::base::StringView func; | |
int line; | |
sf::base::I64 timeUs; | |
sf::base::SizeT nodeId; | |
sf::base::SizeT parentNodeId; | |
sf::base::SizeT depth; | |
}; | |
} // namespace sfex | |
namespace sfex::priv | |
{ | |
//////////////////////////////////////////////////////////// | |
inline constexpr sf::base::SizeT maxNodes = 128u; | |
inline constexpr auto nullNode = static_cast<sf::base::SizeT>(-1); | |
//////////////////////////////////////////////////////////// | |
struct [[nodiscard]] Database | |
{ | |
//////////////////////////////////////////////////////////// | |
ScopeInfo nodes[priv::maxNodes]{}; | |
sf::base::SizeT nextNodeId = 0u; | |
sf::base::SizeT currentNodeId = priv::nullNode; | |
sf::base::SizeT currentDepth = 0u; | |
//////////////////////////////////////////////////////////// | |
[[nodiscard]] ScopeInfo& initNode(const sf::base::StringView label, | |
const sf::base::StringView file, | |
const sf::base::StringView func, | |
const int line) | |
{ | |
const sf::base::SizeT id = nextNodeId++; | |
SFML_BASE_ASSERT(id < priv::maxNodes); | |
nodes[id] = ScopeInfo{ | |
.label = label, | |
.file = file, | |
.func = func, | |
.line = line, | |
.timeUs = 0, | |
.nodeId = id, | |
.parentNodeId = nullNode, | |
.depth = currentDepth, | |
}; | |
return nodes[id]; | |
} | |
}; | |
//////////////////////////////////////////////////////////// | |
inline thread_local Database tlDatabase; | |
} // namespace sfex::priv | |
namespace sfex | |
{ | |
//////////////////////////////////////////////////////////// | |
struct [[nodiscard]] ScopeGuard | |
{ | |
//////////////////////////////////////////////////////////// | |
ScopeInfo& scopeInfo; | |
sf::Time startTime; | |
sf::base::SizeT previousNodeId; | |
//////////////////////////////////////////////////////////// | |
[[gnu::always_inline]] explicit ScopeGuard(ScopeInfo& theScopeInfo) : | |
scopeInfo{theScopeInfo}, | |
startTime{sf::Clock::now()}, | |
previousNodeId{priv::tlDatabase.currentNodeId} | |
{ | |
scopeInfo.parentNodeId = priv::tlDatabase.currentNodeId; | |
priv::tlDatabase.currentNodeId = scopeInfo.nodeId; | |
priv::tlDatabase.currentDepth = scopeInfo.depth + 1u; | |
} | |
//////////////////////////////////////////////////////////// | |
[[gnu::always_inline]] ~ScopeGuard() | |
{ | |
scopeInfo.timeUs = (sf::Clock::now() - startTime).asMicroseconds(); | |
priv::tlDatabase.currentNodeId = previousNodeId; | |
priv::tlDatabase.currentDepth = scopeInfo.depth; | |
} | |
}; | |
} // namespace sfex | |
namespace sfex | |
{ | |
//////////////////////////////////////////////////////////// | |
[[nodiscard, gnu::always_inline]] inline sf::base::Span<const ScopeInfo> getScopeInfos() | |
{ | |
return sf::base::Span<const ScopeInfo>{priv::tlDatabase.nodes, priv::tlDatabase.nextNodeId}; | |
} | |
} // namespace sfex | |
//////////////////////////////////////////////////////////// | |
#define SFEX_PRIV_CONCAT_TOKENS_IMPL(a, b) a##b | |
//////////////////////////////////////////////////////////// | |
#define SFEX_PRIV_CONCAT_TOKENS(a, b) SFEX_PRIV_CONCAT_TOKENS_IMPL(a, b) | |
//////////////////////////////////////////////////////////// | |
#define SFEX_PRIV_UNIQUE_NAME(name) SFEX_PRIV_CONCAT_TOKENS(name, __LINE__) | |
//////////////////////////////////////////////////////////// | |
#define SFEX_PROFILER_SCOPE(label) \ | |
\ | |
static thread_local auto& SFEX_PRIV_UNIQUE_NAME( \ | |
sfProfilerScopeInfo) = ::sfex::priv::tlDatabase.initNode((label), __FILE__, __func__, __LINE__); \ | |
\ | |
const ::sfex::ScopeGuard SFEX_PRIV_UNIQUE_NAME(sfProfilerScopeGuard)(SFEX_PRIV_UNIQUE_NAME(sfProfilerScopeInfo)) | |
//////////////////////////////////////////////////////////// | |
/// \class sf::Profiler | |
/// \ingroup system | |
/// | |
/// TODO P1: docs | |
/// | |
/// \see TODO P1: docs | |
/// | |
//////////////////////////////////////////////////////////// |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment