#ifndef __TRACYVIEW_HPP__ #define __TRACYVIEW_HPP__ #include #include #include #include #include #include #include #include "TracyBuzzAnim.hpp" #include "TracyDecayValue.hpp" #include "TracyTexture.hpp" #include "TracyUserData.hpp" #include "TracyVector.hpp" #include "TracyWorker.hpp" #include "tracy_flat_hash_map.hpp" struct ImVec2; struct ImFont; namespace tracy { struct MemoryPage; struct QueueItem; class FileRead; class TextEditor; class View { struct Animation { bool active = false; int64_t start0, start1; int64_t end0, end1; double progress; }; struct Region { bool active = false; int64_t start; int64_t end; }; public: struct VisData { bool visible = true; bool showFull = true; int offset = 0; int height = 0; }; struct PlotView { double min; double max; }; using SetTitleCallback = void(*)( const char* ); View( ImFont* fixedWidth = nullptr, ImFont* smallFont = nullptr, ImFont* bigFont = nullptr, SetTitleCallback stcb = nullptr ) : View( "127.0.0.1", fixedWidth, smallFont, bigFont, stcb ) {} View( const char* addr, ImFont* fixedWidth = nullptr, ImFont* smallFont = nullptr, ImFont* bigFont = nullptr, SetTitleCallback stcb = nullptr ); View( FileRead& f, ImFont* fixedWidth = nullptr, ImFont* smallFont = nullptr, ImFont* bigFont = nullptr, SetTitleCallback stcb = nullptr ); ~View(); static bool Draw(); void NotifyRootWindowSize( float w, float h ) { m_rootWidth = w; m_rootHeight = h; } void SetTextEditorFile( const char* fileName, int line ); private: enum class Namespace : uint8_t { Full, Mid, Short }; enum class ShortcutAction : uint8_t { None, OpenFind }; enum { InvalidId = 0xFFFFFFFF }; struct PathData { uint32_t cnt; uint64_t mem; }; void InitTextEditor(); const char* ShortenNamespace( const char* name ) const; void DrawHelpMarker( const char* desc ) const; void DrawTextContrast( ImDrawList* draw, const ImVec2& pos, uint32_t color, const char* text ); bool DrawImpl(); bool DrawConnection(); void DrawFrames(); bool DrawZoneFramesHeader(); bool DrawZoneFrames( const FrameData& frames ); void DrawZones(); void DrawContextSwitches( const ContextSwitch* ctx, bool hover, double pxns, int64_t nspx, const ImVec2& wpos, int offset ); int DispatchZoneLevel( const Vector& vec, bool hover, double pxns, int64_t nspx, const ImVec2& wpos, int offset, int depth, float yMin, float yMax ); int DrawZoneLevel( const Vector& vec, bool hover, double pxns, int64_t nspx, const ImVec2& wpos, int offset, int depth, float yMin, float yMax ); int SkipZoneLevel( const Vector& vec, bool hover, double pxns, int64_t nspx, const ImVec2& wpos, int offset, int depth, float yMin, float yMax ); int DispatchGpuZoneLevel( const Vector& vec, bool hover, double pxns, int64_t nspx, const ImVec2& wpos, int offset, int depth, uint64_t thread, float yMin, float yMax, int64_t begin, int drift ); int DrawGpuZoneLevel( const Vector& vec, bool hover, double pxns, int64_t nspx, const ImVec2& wpos, int offset, int depth, uint64_t thread, float yMin, float yMax, int64_t begin, int drift ); int SkipGpuZoneLevel( const Vector& vec, bool hover, double pxns, int64_t nspx, const ImVec2& wpos, int offset, int depth, uint64_t thread, float yMin, float yMax, int64_t begin, int drift ); void DrawLockHeader( uint32_t id, const LockMap& lockmap, const SourceLocation& srcloc, bool hover, ImDrawList* draw, const ImVec2& wpos, float w, float ty, float offset, uint8_t tid ); int DrawLocks( uint64_t tid, bool hover, double pxns, const ImVec2& wpos, int offset, LockHighlight& highlight, float yMin, float yMax ); int DrawPlots( int offset, double pxns, const ImVec2& wpos, bool hover, float yMin, float yMax ); void DrawPlotPoint( const ImVec2& wpos, float x, float y, int offset, uint32_t color, bool hover, bool hasPrev, const PlotItem* item, double prev, bool merged, PlotType type, float PlotHeight ); void DrawPlotPoint( const ImVec2& wpos, float x, float y, int offset, uint32_t color, bool hover, bool hasPrev, double val, double prev, bool merged, PlotType type, float PlotHeight ); int DrawCpuData( int offset, double pxns, const ImVec2& wpos, bool hover, float yMin, float yMax ); void DrawOptions(); void DrawMessages(); void DrawFindZone(); void DrawStatistics(); void DrawMemory(); void DrawAllocList(); void DrawCompare(); void DrawCallstackWindow(); void DrawMemoryAllocWindow(); void DrawInfo(); void DrawTextEditor(); void DrawGoToFrame(); void DrawLockInfoWindow(); void DrawPlayback(); template void ListMemData( T ptr, T end, std::function DrawAddress, const char* id = nullptr, int64_t startTime = -1 ); flat_hash_map> GetCallstackPaths( const MemData& mem, bool onlyActive ) const; flat_hash_map> GetCallstackFrameTreeBottomUp( const MemData& mem ) const; flat_hash_map> GetCallstackFrameTreeTopDown( const MemData& mem ) const; void DrawFrameTreeLevel( const flat_hash_map>& tree, int& idx ); void DrawZoneList( const Vector& zones ); void DrawInfoWindow(); void DrawZoneInfoWindow(); void DrawGpuInfoWindow(); void HandleZoneViewMouse( int64_t timespan, const ImVec2& wpos, float w, double& pxns ); uint32_t GetZoneColor( const ZoneEvent& ev ); uint32_t GetZoneColor( const GpuEvent& ev ); uint32_t GetZoneHighlight( const ZoneEvent& ev ); uint32_t GetZoneHighlight( const GpuEvent& ev ); float GetZoneThickness( const ZoneEvent& ev ); float GetZoneThickness( const GpuEvent& ev ); void ZoomToZone( const ZoneEvent& ev ); void ZoomToZone( const GpuEvent& ev ); void ZoomToRange( int64_t start, int64_t end ); void ZoomToPrevFrame(); void ZoomToNextFrame(); void CenterAtTime( int64_t t ); void ShowZoneInfo( const ZoneEvent& ev ); void ShowZoneInfo( const GpuEvent& ev, uint64_t thread ); void ZoneTooltip( const ZoneEvent& ev ); void ZoneTooltip( const GpuEvent& ev ); void CallstackTooltip( uint32_t idx ); void CrashTooltip(); const ZoneEvent* GetZoneParent( const ZoneEvent& zone ) const; const GpuEvent* GetZoneParent( const GpuEvent& zone ) const; const ThreadData* GetZoneThreadData( const ZoneEvent& zone ) const; uint64_t GetZoneThread( const ZoneEvent& zone ) const; uint64_t GetZoneThread( const GpuEvent& zone ) const; const GpuCtxData* GetZoneCtx( const GpuEvent& zone ) const; const ZoneEvent* FindZoneAtTime( uint64_t thread, int64_t time ) const; const char* GetFrameText( const FrameData& fd, int i, uint64_t ftime, uint64_t offset ) const; #ifndef TRACY_NO_STATISTICS void FindZones(); void FindZonesCompare(); #endif std::vector GetMemoryPages() const; const char* GetPlotName( const PlotData* plot ) const; void SmallCallstackButton( const char* name, uint32_t callstack, int& idx, bool tooltip = true ); void SetViewToLastFrames(); int64_t GetZoneChildTime( const ZoneEvent& zone ); int64_t GetZoneChildTime( const GpuEvent& zone ); int64_t GetZoneChildTimeFast( const ZoneEvent& zone ); int64_t GetZoneSelfTime( const ZoneEvent& zone ); int64_t GetZoneSelfTime( const GpuEvent& zone ); bool GetZoneRunningTime( const ContextSwitch* ctx, const ZoneEvent& ev, int64_t& time, uint64_t& cnt ); void SetPlaybackFrame( uint32_t idx ); flat_hash_map> m_visData; flat_hash_map> m_visibleMsgThread; flat_hash_map> m_gpuDrift; flat_hash_map> m_plotView; Vector m_threadOrder; Vector m_threadDnd; tracy_force_inline VisData& Vis( const void* ptr ) { auto it = m_visData.find( ptr ); if( it == m_visData.end() ) { it = m_visData.emplace( ptr, VisData {} ).first; } return it->second; } tracy_force_inline bool& VisibleMsgThread( uint64_t thread ) { auto it = m_visibleMsgThread.find( thread ); if( it == m_visibleMsgThread.end() ) { it = m_visibleMsgThread.emplace( thread, true ).first; } return it->second; } tracy_force_inline int& GpuDrift( const void* ptr ) { auto it = m_gpuDrift.find( ptr ); if( it == m_gpuDrift.end() ) { it = m_gpuDrift.emplace( ptr, 0 ).first; } return it->second; } Worker m_worker; bool m_staticView; int m_frameScale = 0; bool m_pause; int m_frameStart = 0; int64_t m_zvStart = 0; int64_t m_zvEnd = 0; int m_zvHeight = 0; int m_zvScroll = 0; const ZoneEvent* m_zoneInfoWindow = nullptr; const ZoneEvent* m_zoneHighlight; DecayValue m_zoneSrcLocHighlight = 0; LockHighlight m_lockHighlight { -1 }; DecayValue m_msgHighlight = nullptr; DecayValue m_lockHoverHighlight = InvalidId; DecayValue m_msgToFocus = nullptr; const GpuEvent* m_gpuInfoWindow = nullptr; const GpuEvent* m_gpuHighlight; uint64_t m_gpuInfoWindowThread; uint32_t m_callstackInfoWindow = 0; int64_t m_memoryAllocInfoWindow = -1; int64_t m_memoryAllocHover = -1; int m_memoryAllocHoverWait = 0; const FrameData* m_frames; uint32_t m_lockInfoWindow = InvalidId; ZoneEvent* m_zoneHover = nullptr; int m_frameHover = -1; bool m_messagesScrollBottom; ImGuiTextFilter m_messageFilter; int m_visibleMessages = 0; bool m_disconnectIssued = false; Region m_highlight; Region m_highlightZoom; uint64_t m_gpuThread = 0; int64_t m_gpuStart = 0; int64_t m_gpuEnd = 0; bool m_showOptions = false; bool m_showMessages = false; bool m_showStatistics = false; bool m_showInfo = false; bool m_showPlayback = false; bool m_drawGpuZones = true; bool m_drawZones = true; bool m_drawLocks = true; bool m_drawPlots = true; bool m_onlyContendedLocks = true; bool m_goToFrame = false; bool m_drawEmptyLabels = false; bool m_drawContextSwitches = true; bool m_drawCpuData = true; int m_statSort = 0; bool m_statSelf = false; bool m_showCallstackFrameAddress = false; bool m_showUnknownFrames = true; bool m_groupChildrenLocations = false; bool m_allocTimeRelativeToZone = true; bool m_ctxSwitchTimeRelativeToZone = true; ShortcutAction m_shortcut = ShortcutAction::None; Namespace m_namespace = Namespace::Short; Animation m_zoomAnim; BuzzAnim m_callstackBuzzAnim; BuzzAnim m_callstackTreeBuzzAnim; BuzzAnim m_zoneinfoBuzzAnim; BuzzAnim m_findZoneBuzzAnim; BuzzAnim m_optionsLockBuzzAnim; BuzzAnim m_lockInfoAnim; BuzzAnim m_statBuzzAnim; Vector m_zoneInfoStack; Vector m_gpuInfoStack; std::unique_ptr m_textEditor; const char* m_textEditorFile; ImFont* m_textEditorFont; bool m_textEditorWhitespace = true; ImFont* m_smallFont; ImFont* m_bigFont; float m_rootWidth, m_rootHeight; SetTitleCallback m_stcb; bool m_titleSet = false; float m_notificationTime = 0; std::string m_notificationText; bool m_groupCallstackTreeByNameBottomUp = true; bool m_groupCallstackTreeByNameTopDown = true; bool m_activeOnlyBottomUp = false; bool m_activeOnlyTopDown = false; enum class SaveThreadState { Inert, Saving, NeedsJoin }; std::atomic m_saveThreadState { SaveThreadState::Inert }; std::thread m_saveThread; void* m_frameTexture = nullptr; const void* m_frameTexturePtr = nullptr; UserData m_userData; struct FindZone { enum : uint64_t { Unselected = std::numeric_limits::max() - 1 }; enum class GroupBy : int { Thread, UserText, Callstack }; enum class SortBy : int { Order, Count, Time, Mtpc }; enum class TableSortBy : int { Starttime, Runtime, Name }; struct Group { Vector zones; int64_t time = 0; }; bool show = false; bool ignoreCase = false; std::vector match; std::map groups; size_t processed; int selMatch = 0; uint64_t selGroup = Unselected; char pattern[1024] = {}; bool logVal = false; bool logTime = true; bool cumulateTime = false; bool selfTime = false; bool runningTime = false; GroupBy groupBy = GroupBy::Thread; SortBy sortBy = SortBy::Count; TableSortBy tableSortBy = TableSortBy::Starttime; Region highlight; int64_t hlOrig_t0, hlOrig_t1; int64_t numBins = -1; std::unique_ptr bins, binTime, selBin; std::vector sorted, selSort; size_t sortedNum = 0, selSortNum, selSortActive; float average, selAverage; float median, selMedian; int64_t total, selTotal; bool drawAvgMed = true; bool drawSelAvgMed = true; bool scheduleResetMatch = false; int selCs = 0; int minBinVal = 1; int64_t tmin, tmax; struct { int numBins = -1; ptrdiff_t distBegin; ptrdiff_t distEnd; } binCache; void Reset() { ResetMatch(); match.clear(); selMatch = 0; selGroup = Unselected; highlight.active = false; } void ResetMatch() { ResetGroups(); sorted.clear(); sortedNum = 0; average = 0; median = 0; total = 0; tmin = std::numeric_limits::max(); tmax = std::numeric_limits::min(); } void ResetGroups() { ResetSelection(); groups.clear(); processed = 0; selCs = 0; } void ResetSelection() { selSort.clear(); selSortNum = 0; selSortActive = 0; selAverage = 0; selMedian = 0; selTotal = 0; binCache.numBins = -1; } void ShowZone( int16_t srcloc, const char* name ) { show = true; Reset(); match.emplace_back( srcloc ); strcpy( pattern, name ); } } m_findZone; tracy_force_inline uint64_t GetSelectionTarget( const Worker::ZoneThreadData& ev, FindZone::GroupBy groupBy ) const; struct CompVal { double v0; double v1; }; struct { bool show = false; bool ignoreCase = false; bool link = true; std::unique_ptr second; std::unique_ptr userData; std::thread loadThread; BadVersionState badVer; char pattern[1024] = {}; std::vector match[2]; int selMatch[2] = { 0, 0 }; bool logVal = false; bool logTime = true; bool cumulateTime = false; bool normalize = true; int64_t numBins = -1; std::unique_ptr bins, binTime; std::vector sorted[2]; size_t sortedNum[2] = { 0, 0 }; float average[2]; float median[2]; int64_t total[2]; int minBinVal = 1; void ResetSelection() { for( int i=0; i<2; i++ ) { sorted[i].clear(); sortedNum[i] = 0; average[i] = 0; median[i] = 0; total[i] = 0; } } void Reset() { ResetSelection(); for( int i=0; i<2; i++ ) { match[i].clear(); selMatch[i] = 0; } } } m_compare; struct { bool show = false; char pattern[1024] = {}; uint64_t ptrFind = 0; bool restrictTime = false; bool showAllocList = false; std::vector allocList; } m_memInfo; struct { std::vector data; const FrameData* frameSet = nullptr; size_t frameNum = 0; float average = 0; float median = 0; int64_t total = 0; bool logVal = false; bool logTime = true; int64_t numBins = -1; std::unique_ptr bins; bool drawAvgMed = true; bool limitToView = false; std::pair limitRange = { -1, 0 }; int minBinVal = 1; } m_frameSortData; struct { std::pair zoneSelfTime = { nullptr, 0 }; std::pair zoneSelfTime2 = { nullptr, 0 }; std::pair gpuSelfTime = { nullptr, 0 }; std::pair gpuSelfTime2 = { nullptr, 0 }; } m_cache; struct { void* texture = nullptr; float timeLeft = 0; float speed = 1; uint32_t frame = 0; uint32_t currFrame = -1; bool pause = true; bool sync = false; bool zoom = false; } m_playback; }; } #endif