From d536a95f4ae46ba9b521827a70d67730b665f8fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 11 Oct 2024 13:06:04 +0200 Subject: [PATCH] DebugTools: use steady_clock for FrameProfiler CPU timing. Otherwise it may happen that the clock gets adjusted mid-frame, leading to an underflow and an assertion like this: Assertion _measurements[i]._movingSum + data >= _measurements[i]._movingSum failed at src/Magnum/DebugTools/FrameProfiler.cpp:233 The clock adjustment is known to be happening rather frequently under WSL2. --- src/Magnum/DebugTools/FrameProfiler.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Magnum/DebugTools/FrameProfiler.cpp b/src/Magnum/DebugTools/FrameProfiler.cpp index b388f0040..1f06bcbdb 100644 --- a/src/Magnum/DebugTools/FrameProfiler.cpp +++ b/src/Magnum/DebugTools/FrameProfiler.cpp @@ -476,7 +476,11 @@ void FrameProfilerGL::setup(const Values values, const UnsignedInt maxFrameCount arrayAppend(measurements, InPlaceInit, "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(); + /* Using steady_clock even though it might not be as precise as + high_resolution_clock in order to avoid the delta being + negative between frames, causing an underflow and an assert + similar to what used to happen for PrimitiveClipRatio */ + static_cast(state)->frameTimeStartFrame[current] = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); }, [](void*, UnsignedInt) {}, [](void* state, UnsignedInt previous, UnsignedInt current) { @@ -490,11 +494,15 @@ void FrameProfilerGL::setup(const Values values, const UnsignedInt maxFrameCount arrayAppend(measurements, InPlaceInit, "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(); + /* Using steady_clock even though it might not be as precise as + high_resolution_clock in order to avoid the delta being + negative between frames, causing an underflow and an assert + similar to what used to happen for PrimitiveClipRatio */ + static_cast(state)->cpuDurationStartFrame = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); }, [](void* state) { /* libc++ 10 needs an explicit cast to UnsignedLong */ - return UnsignedLong(std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count() - static_cast(state)->cpuDurationStartFrame); + return UnsignedLong(std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count() - static_cast(state)->cpuDurationStartFrame); }, _state.get()); _state->cpuDurationIndex = index++; }