From cec3c21c301364d910743f9a81589b3babf2ccd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 31 Dec 2022 03:03:35 +0100 Subject: [PATCH] DebugTools: port FrameProfiler away from std::string. One of the last remaining leftovers. --- doc/changelog.dox | 4 ++ src/Magnum/DebugTools/FrameProfiler.cpp | 45 ++++++++++--------- src/Magnum/DebugTools/FrameProfiler.h | 45 ++++++++++++++----- .../DebugTools/Test/FrameProfilerGLTest.cpp | 8 +++- 4 files changed, 68 insertions(+), 34 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 7ecf58505..3320fa7bc 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -1137,6 +1137,10 @@ See also: - As part of the ongoing STL header dependency cleanup, the following breaking changes related to @ref std::string, @ref std::vector and @ref std::pair are done: + - @ref DebugTools::FrameProfiler::measurementName() and + @ref DebugTools::FrameProfiler::statistics() now return a + @relativeref{Corrade,Containers::StringView} / + @relativeref{Corrade,Containers::String} instead of a @ref std::string - @ref GL::AbstractShaderProgram::validate() now returns a @relativeref{Corrade,Containers::Pair} with a @relativeref{Corrade,Containers::String} instead of a @ref std::pair diff --git a/src/Magnum/DebugTools/FrameProfiler.cpp b/src/Magnum/DebugTools/FrameProfiler.cpp index 41cb41b9e..1e447eed4 100644 --- a/src/Magnum/DebugTools/FrameProfiler.cpp +++ b/src/Magnum/DebugTools/FrameProfiler.cpp @@ -31,9 +31,9 @@ #include #include #include -#include +#include +#include /** @todo drop once Debug is stream-free */ #include -#include #include "Magnum/Math/Functions.h" #ifdef MAGNUM_TARGET_GL @@ -45,12 +45,14 @@ namespace Magnum { namespace DebugTools { -FrameProfiler::Measurement::Measurement(const std::string& name, const Units units, void(*const begin)(void*), UnsignedLong(*const end)(void*), void* const state): _name{name}, _end{nullptr}, _state{state}, _units{units}, _delay{0} { +using namespace Containers::Literals; + +FrameProfiler::Measurement::Measurement(const Containers::StringView name, const Units units, void(*const begin)(void*), UnsignedLong(*const end)(void*), void* const state): _name{Containers::String::nullTerminatedGlobalView(name)}, _end{nullptr}, _state{state}, _units{units}, _delay{0} { _begin.immediate = begin; _query.immediate = end; } -FrameProfiler::Measurement::Measurement(const std::string& name, const Units units, const UnsignedInt delay, void(*const begin)(void*, UnsignedInt), void(*const end)(void*, UnsignedInt), UnsignedLong(*const query)(void*, UnsignedInt, UnsignedInt), void* const state): _name{name}, _state{state}, _units{units}, _delay{delay} { +FrameProfiler::Measurement::Measurement(const Containers::StringView name, const Units units, const UnsignedInt delay, void(*const begin)(void*, UnsignedInt), void(*const end)(void*, UnsignedInt), UnsignedLong(*const query)(void*, UnsignedInt, UnsignedInt), void* const state): _name{Containers::String::nullTerminatedGlobalView(name)}, _state{state}, _units{units}, _delay{delay} { CORRADE_ASSERT(delay >= 1, "DebugTools::FrameProfiler::Measurement: delay can't be zero", ); _begin.delayed = begin; _end = end; @@ -234,7 +236,7 @@ void FrameProfiler::endFrame() { } } -std::string FrameProfiler::measurementName(const UnsignedInt id) const { +Containers::StringView FrameProfiler::measurementName(const UnsignedInt id) const { CORRADE_ASSERT(id < _measurements.size(), "DebugTools::FrameProfiler::measurementName(): index" << id << "out of range for" << _measurements.size() << "measurements", {}); return _measurements[id]._name; @@ -379,7 +381,7 @@ void FrameProfiler::printStatisticsInternal(Debug& out) const { } } -std::string FrameProfiler::statistics() const { +Containers::String FrameProfiler::statistics() const { std::ostringstream out; Debug d{&out, Debug::Flag::NoNewlineAtTheEnd|Debug::Flag::DisableColors}; printStatisticsInternal(d); @@ -471,7 +473,7 @@ void FrameProfilerGL::setup(const Values values, const UnsignedInt maxFrameCount should have flipped the table and learn carpentry instead. BUT NO, I'm still suffering this abomination a decade later! */ arrayAppend(measurements, InPlaceInit, - "Frame time", Units::Nanoseconds, UnsignedInt(Containers::arraySize(_state->frameTimeStartFrame)), + "Frame time"_s, Units::Nanoseconds, UnsignedInt(Containers::arraySize(_state->frameTimeStartFrame)), [](void* state, UnsignedInt current) { static_cast(state)->frameTimeStartFrame[current] = std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count(); }, @@ -485,7 +487,7 @@ void FrameProfilerGL::setup(const Values values, const UnsignedInt maxFrameCount } if(values & Value::CpuDuration) { arrayAppend(measurements, InPlaceInit, - "CPU duration", Units::Nanoseconds, + "CPU duration"_s, Units::Nanoseconds, [](void* state) { static_cast(state)->cpuDurationStartFrame = std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count(); }, @@ -499,7 +501,7 @@ void FrameProfilerGL::setup(const Values values, const UnsignedInt maxFrameCount for(GL::TimeQuery& q: _state->timeQueries) q = GL::TimeQuery{GL::TimeQuery::Target::TimeElapsed}; arrayAppend(measurements, InPlaceInit, - "GPU duration", Units::Nanoseconds, + "GPU duration"_s, Units::Nanoseconds, UnsignedInt(_state->timeQueries.size()), [](void* state, UnsignedInt current) { static_cast(state)->timeQueries[current].begin(); @@ -519,7 +521,7 @@ void FrameProfilerGL::setup(const Values values, const UnsignedInt maxFrameCount for(GL::PipelineStatisticsQuery& q: _state->vertexShaderInvocationsQueries) q = GL::PipelineStatisticsQuery{GL::PipelineStatisticsQuery::Target::VertexShaderInvocations}; arrayAppend(measurements, InPlaceInit, - "Vertex fetch ratio", Units::RatioThousandths, + "Vertex fetch ratio"_s, Units::RatioThousandths, UnsignedInt(_state->verticesSubmittedQueries.size()), [](void* state, UnsignedInt current) { static_cast(state)->verticesSubmittedQueries[current].begin(); @@ -544,7 +546,7 @@ void FrameProfilerGL::setup(const Values values, const UnsignedInt maxFrameCount for(GL::PipelineStatisticsQuery& q: _state->clippingOutputPrimitivesQueries) q = GL::PipelineStatisticsQuery{GL::PipelineStatisticsQuery::Target::ClippingOutputPrimitives}; arrayAppend(measurements, InPlaceInit, - "Primitives clipped", Units::PercentageThousandths, + "Primitives clipped"_s, Units::PercentageThousandths, UnsignedInt(_state->clippingInputPrimitivesQueries.size()), [](void* state, UnsignedInt current) { static_cast(state)->clippingInputPrimitivesQueries[current].begin(); @@ -674,17 +676,18 @@ Debug& operator<<(Debug& debug, const FrameProfilerGL::Values value) { namespace Corrade { namespace Utility { +using namespace Containers::Literals; using namespace Magnum; #ifdef MAGNUM_TARGET_GL -std::string ConfigurationValue::toString(const DebugTools::FrameProfilerGL::Value value, ConfigurationValueFlags) { +Containers::StringView ConfigurationValue::toString(const DebugTools::FrameProfilerGL::Value value, ConfigurationValueFlags) { const UnsignedInt bit = Math::log2(UnsignedShort(value)); if(1 << bit == UnsignedShort(value)) return DebugTools::FrameProfilerGLValueNames[bit]; return ""; } -DebugTools::FrameProfilerGL::Value ConfigurationValue::fromString(const std::string& value, ConfigurationValueFlags) { +DebugTools::FrameProfilerGL::Value ConfigurationValue::fromString(const Containers::StringView value, ConfigurationValueFlags) { for(std::size_t i = 0; i != Containers::arraySize(DebugTools::FrameProfilerGLValueNames); ++i) if(DebugTools::FrameProfilerGLValueNames[i] == value) return DebugTools::FrameProfilerGL::Value(1 << i); @@ -692,25 +695,27 @@ DebugTools::FrameProfilerGL::Value ConfigurationValue::toString(const DebugTools::FrameProfilerGL::Values value, ConfigurationValueFlags) { - std::string out; +Containers::String ConfigurationValue::toString(const DebugTools::FrameProfilerGL::Values value, ConfigurationValueFlags) { + Containers::String out; for(std::size_t i = 0; i != Containers::arraySize(DebugTools::FrameProfilerGLValueNames); ++i) { const auto bit = DebugTools::FrameProfilerGL::Value(1 << i); if(value & bit) { - if(!out.empty()) out += ' '; - out += DebugTools::FrameProfilerGLValueNames[i]; + /** @todo ugh, one allocation per bit, fix when growable String is + a thing ... or maybe some "get set bits" utility and then call + join just once? */ + out = " "_s.joinWithoutEmptyParts({out, DebugTools::FrameProfilerGLValueNames[i]}); } } return out; } -DebugTools::FrameProfilerGL::Values ConfigurationValue::fromString(const std::string& value, ConfigurationValueFlags) { - const std::vector bits = Utility::String::splitWithoutEmptyParts(value); +DebugTools::FrameProfilerGL::Values ConfigurationValue::fromString(const Containers::StringView value, ConfigurationValueFlags) { + const Containers::Array bits = value.splitOnWhitespaceWithoutEmptyParts(); DebugTools::FrameProfilerGL::Values values; - for(const std::string& bit: bits) + for(const Containers::StringView bit: bits) for(std::size_t i = 0; i != Containers::arraySize(DebugTools::FrameProfilerGLValueNames); ++i) if(DebugTools::FrameProfilerGLValueNames[i] == bit) values |= DebugTools::FrameProfilerGL::Value(1 << i); diff --git a/src/Magnum/DebugTools/FrameProfiler.h b/src/Magnum/DebugTools/FrameProfiler.h index 81e1aebbf..b02835961 100644 --- a/src/Magnum/DebugTools/FrameProfiler.h +++ b/src/Magnum/DebugTools/FrameProfiler.h @@ -30,13 +30,20 @@ * @m_since{2020,06} */ -#include #include #include +#include #include "Magnum/Magnum.h" #include "Magnum/DebugTools/visibility.h" +#ifdef MAGNUM_BUILD_DEPRECATED +/* Measurement used to take a std::string, measurementName() and statistics() + used to be a std::string. Not ideal for the return types, but at least + something. */ +#include +#endif + namespace Magnum { namespace DebugTools { /** @@ -289,9 +296,13 @@ class MAGNUM_DEBUGTOOLS_EXPORT FrameProfiler { * * The @p id corresponds to the index of the measurement in the list * passed to @ref setup(). Expects that @p id is less than - * @ref measurementCount(). + * @ref measurementCount(). The returned view is always + * @relativeref{Corrade,Containers::StringViewFlag::NullTerminated}; + * @relativeref{Corrade,Containers::StringViewFlag::Global} is set if + * the corresponding @ref Measurement was created with a global + * null-terminated string view. */ - std::string measurementName(UnsignedInt id) const; + Containers::StringView measurementName(UnsignedInt id) const; /** * @brief Measurement units @@ -359,7 +370,7 @@ class MAGNUM_DEBUGTOOLS_EXPORT FrameProfiler { * is not available yet, prints placeholder values for these. * @see @ref isMeasurementAvailable(), @ref isEnabled() */ - std::string statistics() const; + Containers::String statistics() const; /** * @brief Print an overview of all measurements to a console at given rate @@ -427,8 +438,12 @@ class MAGNUM_DEBUGTOOLS_EXPORT FrameProfiler::Measurement { * the measured value * @param state State pointer passed to both @p begin and @p end * as a first argument + * + * If @p name is @relativeref{Corrade,Containers::StringViewFlag::NullTerminated} + * and @relativeref{Corrade::Containers::StringViewFlag,Global}, no + * internal copy of the string is made. */ - explicit Measurement(const std::string& name, Units units, void(*begin)(void*), UnsignedLong(*end)(void*), void* state); + explicit Measurement(Containers::StringView name, Units units, void(*begin)(void*), UnsignedLong(*end)(void*), void* state); /** * @brief Construct a delayed measurement @@ -458,13 +473,17 @@ class MAGNUM_DEBUGTOOLS_EXPORT FrameProfiler::Measurement { * corresponds to current frame. * @param state State pointer passed to both @p begin and @p end * as a first argument + * + * If @p name is @relativeref{Corrade,Containers::StringViewFlag::NullTerminated} + * and @relativeref{Corrade::Containers::StringViewFlag,Global}, no + * internal copy of the string is made. */ - explicit Measurement(const std::string& name, Units units, UnsignedInt delay, void(*begin)(void*, UnsignedInt), void(*end)(void*, UnsignedInt), UnsignedLong(*query)(void*, UnsignedInt, UnsignedInt), void* state); + explicit Measurement(Containers::StringView name, Units units, UnsignedInt delay, void(*begin)(void*, UnsignedInt), void(*end)(void*, UnsignedInt), UnsignedLong(*query)(void*, UnsignedInt, UnsignedInt), void* state); private: friend FrameProfiler; - std::string _name; + Containers::String _name; union { void(*immediate)(void*); void(*delayed)(void*, UnsignedInt); @@ -733,16 +752,18 @@ template<> struct MAGNUM_DEBUGTOOLS_EXPORT ConfigurationValue struct MAGNUM_DEBUGTOOLS_EXPORT ConfigurationValue struct MAGNUM_DEBUGTOOLS_EXPORT ConfigurationValue