Adding log-scale option for displaying plot data.

This commit is contained in:
Marcos Slomp
2026-10-28 06:31:36 -07:00
parent 9f1c8e652c
commit 7e512af1d2
5 changed files with 73 additions and 6 deletions
@@ -0,0 +1,45 @@
#ifndef __TRACYPLOTMAPPING_HPP__
#define __TRACYPLOTMAPPING_HPP__
#include <math.h>
#include <stdint.h>
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
@@ -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() );
@@ -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;
+3
View File
@@ -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<uint32_t>& plotDraw, int& offset, bool rightEnd );
void DrawThread( const TimelineContext& ctx, const ThreadData& thread, const std::vector<TimelineDraw>& draw, const std::vector<ContextSwitchDraw>& ctxDraw, const std::vector<SamplesDraw>& samplesDraw, const std::vector<std::unique_ptr<LockDraw>>& lockDraw, int& offset, int depth, bool hasCtxSwitches, bool hasSamples );
@@ -496,6 +498,7 @@ private:
unordered_flat_map<uint64_t, bool> m_flameGraphThread;
unordered_flat_map<const void*, int> m_gpuDrift;
unordered_flat_map<const PlotData*, PlotView> m_plotView;
unordered_flat_map<const PlotData*, PlotMapping> m_plotMapping;
Vector<const ThreadData*> m_threadOrder;
Vector<const ThreadData*> m_threadReinsert;
Vector<float> m_threadDnd;
+10 -6
View File
@@ -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 );
}