diff --git a/profiler/src/profiler/TracyPlotMapping.hpp b/profiler/src/profiler/TracyPlotMapping.hpp new file mode 100644 index 00000000..c9946f37 --- /dev/null +++ b/profiler/src/profiler/TracyPlotMapping.hpp @@ -0,0 +1,45 @@ +#ifndef __TRACYPLOTMAPPING_HPP__ +#define __TRACYPLOTMAPPING_HPP__ + +#include +#include + +namespace tracy +{ + +// To add a mapping: append an enum value (before Count), then extend PlotMappingName() and MapPlotValue(). +// Mappings must be strictly monotonic increasing and defined for all finite doubles. +enum class PlotMapping : uint8_t +{ + Linear, + SymLog, + Count +}; + +static inline const char* PlotMappingName( PlotMapping mapping ) +{ + switch( mapping ) + { + case PlotMapping::Linear: return "Linear"; + case PlotMapping::SymLog: return "Logarithmic"; + default: return ""; + } +} + +static inline double MapPlotValue( PlotMapping mapping, double v ) +{ + switch( mapping ) + { + case PlotMapping::SymLog: + // sign(v) * log10( 1 + |v| ), computed via log1p to stay accurate for tiny |v| + // TODO(slomp): nearly linear for sub-1 floating-point data; consider scaling by a data-derived constant + return copysign( log1p( fabs( v ) ) * 0.43429448190325176, v ); + case PlotMapping::Linear: + default: + return v; + } +} + +} + +#endif diff --git a/profiler/src/profiler/TracyTimelineItemPlot.cpp b/profiler/src/profiler/TracyTimelineItemPlot.cpp index e39b0bb0..e30115d8 100644 --- a/profiler/src/profiler/TracyTimelineItemPlot.cpp +++ b/profiler/src/profiler/TracyTimelineItemPlot.cpp @@ -120,6 +120,20 @@ void TimelineItemPlot::DrawFinished() m_draw.clear(); } +void TimelineItemPlot::DrawExtraPopupItems() +{ + if( ImGui::BeginMenu( "Y-axis scale" ) ) + { + auto& current = m_view.GetPlotMapping( m_plot ); + for( uint8_t i=0; i<(uint8_t)PlotMapping::Count; i++ ) + { + const auto mapping = (PlotMapping)i; + if( ImGui::MenuItem( PlotMappingName( mapping ), nullptr, current == mapping ) ) current = mapping; + } + ImGui::EndMenu(); + } +} + void TimelineItemPlot::Preprocess( const TimelineContext& ctx, TaskDispatch& td, bool visible, int yPos ) { assert( m_draw.empty() ); diff --git a/profiler/src/profiler/TracyTimelineItemPlot.hpp b/profiler/src/profiler/TracyTimelineItemPlot.hpp index 3ad40509..26f1d7e8 100644 --- a/profiler/src/profiler/TracyTimelineItemPlot.hpp +++ b/profiler/src/profiler/TracyTimelineItemPlot.hpp @@ -27,6 +27,7 @@ protected: void HeaderTooltip( const char* label ) const override; void HeaderExtraContents( const TimelineContext& ctx, int offset, float labelWidth ) override; void HeaderZoomed() override; + void DrawExtraPopupItems() override; bool DrawContents( const TimelineContext& ctx, int& offset ) override; void DrawFinished() override; diff --git a/profiler/src/profiler/TracyView.hpp b/profiler/src/profiler/TracyView.hpp index fc2aca31..7d2c508b 100644 --- a/profiler/src/profiler/TracyView.hpp +++ b/profiler/src/profiler/TracyView.hpp @@ -20,6 +20,7 @@ #include "TracyDecayValue.hpp" #include "TracyManualWindow.hpp" #include "TracyMarkdown.hpp" +#include "TracyPlotMapping.hpp" #include "TracySourceContents.hpp" #include "TracyTimelineController.hpp" #include "TracyTimelineDraw.hpp" @@ -205,6 +206,7 @@ public: void HighlightThread( uint64_t thread ); void SelectThread( uint64_t thread ); uint64_t GetSelectThread() const { return m_selectedThread; } + PlotMapping& GetPlotMapping( const PlotData* plot ) { return m_plotMapping[plot]; } void ZoomToRange( int64_t start, int64_t end, bool pause = true ); bool DrawPlot( const TimelineContext& ctx, PlotData& plot, const std::vector& plotDraw, int& offset, bool rightEnd ); void DrawThread( const TimelineContext& ctx, const ThreadData& thread, const std::vector& draw, const std::vector& ctxDraw, const std::vector& samplesDraw, const std::vector>& lockDraw, int& offset, int depth, bool hasCtxSwitches, bool hasSamples ); @@ -496,6 +498,7 @@ private: unordered_flat_map m_flameGraphThread; unordered_flat_map m_gpuDrift; unordered_flat_map m_plotView; + unordered_flat_map m_plotMapping; Vector m_threadOrder; Vector m_threadReinsert; Vector m_threadDnd; diff --git a/profiler/src/profiler/TracyView_Plots.cpp b/profiler/src/profiler/TracyView_Plots.cpp index 3ce59471..79e59eae 100644 --- a/profiler/src/profiler/TracyView_Plots.cpp +++ b/profiler/src/profiler/TracyView_Plots.cpp @@ -54,6 +54,10 @@ bool View::DrawPlot( const TimelineContext& ctx, PlotData& plot, const std::vect max = pv.max; } + const auto mapping = GetPlotMapping( &plot ); + min = MapPlotValue( mapping, min ); + max = MapPlotValue( mapping, max ); + const auto color = GetPlotColor( plot, m_worker ); const auto bg = 0x22000000 | ( DarkenColorMore( color ) & 0xFFFFFF ); const auto fill = 0x22000000 | ( DarkenColor( color ) & 0xFFFFFF ); @@ -73,7 +77,7 @@ bool View::DrawPlot( const TimelineContext& ctx, PlotData& plot, const std::vect const auto i0 = *it++; const auto& v0 = vec[i0]; double x = ( v0.time.Val() - m_vd.zvStart ) * pxns; - double y = PlotHeight - ( v0.val - min ) * revrange * PlotHeight; + double y = PlotHeight - ( MapPlotValue( mapping, v0.val ) - min ) * revrange * PlotHeight; if( first ) { @@ -119,13 +123,13 @@ bool View::DrawPlot( const TimelineContext& ctx, PlotData& plot, const std::vect const auto i1 = i0 + cnt - 1; const auto& v1 = vec[i1]; px = x; - py = PlotHeight - ( v1.val - min ) * revrange * PlotHeight; + py = PlotHeight - ( MapPlotValue( mapping, v1.val ) - min ) * revrange * PlotHeight; const auto imin = *it++; const auto imax = *it++; const auto vmin = vec[imin].val; const auto vmax = vec[imax].val; - const auto ymin = offset + PlotHeight - ( vmin - min ) * revrange * PlotHeight; - const auto ymax = offset + PlotHeight - ( vmax - min ) * revrange * PlotHeight; + const auto ymin = offset + PlotHeight - ( MapPlotValue( mapping, vmin ) - min ) * revrange * PlotHeight; + const auto ymax = offset + PlotHeight - ( MapPlotValue( mapping, vmax ) - min ) * revrange * PlotHeight; if( cnt < MaxShow ) { DrawLine( draw, dpos + ImVec2( x, ymin ), dpos + ImVec2( x, ymax ), color ); @@ -134,7 +138,7 @@ bool View::DrawPlot( const TimelineContext& ctx, PlotData& plot, const std::vect { const auto is = i0 + i; const auto& vs = vec[is]; - auto ys = PlotHeight - ( vs.val - min ) * revrange * PlotHeight; + auto ys = PlotHeight - ( MapPlotValue( mapping, vs.val ) - min ) * revrange * PlotHeight; DrawPlotPoint( wpos, x, ys, offset, color, hover, vs.val, plot.format, PlotHeight ); } } @@ -190,7 +194,7 @@ bool View::DrawPlot( const TimelineContext& ctx, PlotData& plot, const std::vect else { x0 = ( plot.data.back().time.Val() - m_vd.zvStart ) * pxns; - y = PlotHeight - ( plot.data.back().val - min ) * revrange * PlotHeight; + y = PlotHeight - ( MapPlotValue( mapping, plot.data.back().val ) - min ) * revrange * PlotHeight; DrawLine( draw, dpos + ImVec2( x0, offset + y ), dpos + ImVec2( x1, offset + y ), color ); }