2017-09-14 19:28:40 +00:00
# include <algorithm>
2017-09-12 23:33:50 +00:00
# include <assert.h>
2017-10-21 11:32:51 +00:00
# include <chrono>
2017-09-22 20:11:30 +00:00
# include <inttypes.h>
2017-09-16 23:41:18 +00:00
# include <limits>
2017-10-06 00:19:25 +00:00
# include <math.h>
2017-11-15 20:49:41 +00:00
# include <mutex>
2018-03-13 15:23:10 +00:00
# include <stddef.h>
2017-09-18 23:24:31 +00:00
# include <stdlib.h>
2017-10-03 21:26:41 +00:00
# include <time.h>
2017-09-12 23:33:50 +00:00
# include "../common/TracySystem.hpp"
2017-12-08 22:11:08 +00:00
# include "tracy_pdqsort.h"
2017-09-30 14:20:08 +00:00
# include "TracyFileWrite.hpp"
2017-09-17 22:18:36 +00:00
# include "TracyImGui.hpp"
2017-10-28 21:12:11 +00:00
# include "TracyPopcnt.hpp"
2017-09-12 23:33:50 +00:00
# include "TracyView.hpp"
2017-09-30 12:56:09 +00:00
# ifdef TRACY_FILESELECTOR
# include ".. / nfd / nfd.h"
# endif
2017-09-12 23:33:50 +00:00
namespace tracy
{
2017-10-22 15:47:40 +00:00
static const char * TimeToString ( int64_t ns )
{
enum { Pool = 8 } ;
static char bufpool [ Pool ] [ 64 ] ;
static int bufsel = 0 ;
char * buf = bufpool [ bufsel ] ;
bufsel = ( bufsel + 1 ) % Pool ;
const char * sign = " " ;
if ( ns < 0 )
2017-12-17 17:44:31 +00:00
{
2017-10-22 15:47:40 +00:00
sign = " - " ;
ns = - ns ;
2017-12-17 17:44:31 +00:00
}
2017-10-22 15:47:40 +00:00
if ( ns < 1000 )
2017-12-17 17:44:31 +00:00
{
2017-10-28 19:50:06 +00:00
sprintf ( buf , " %s% " PRIi64 " ns " , sign , ns ) ;
2017-12-17 17:44:31 +00:00
}
2017-10-28 19:50:06 +00:00
else if ( ns < 1000ll * 1000 )
2017-12-17 17:44:31 +00:00
{
2017-10-22 15:47:40 +00:00
sprintf ( buf , " %s%.2f us " , sign , ns / 1000. ) ;
2017-12-17 17:44:31 +00:00
}
2017-10-28 19:50:06 +00:00
else if ( ns < 1000ll * 1000 * 1000 )
2017-10-13 01:36:59 +00:00
{
2017-10-22 15:47:40 +00:00
sprintf ( buf , " %s%.2f ms " , sign , ns / ( 1000. * 1000. ) ) ;
2017-10-13 01:36:59 +00:00
}
2017-10-28 19:50:06 +00:00
else if ( ns < 1000ll * 1000 * 1000 * 60 )
2017-11-20 01:14:18 +00:00
{
2017-10-22 15:47:40 +00:00
sprintf ( buf , " %s%.2f s " , sign , ns / ( 1000. * 1000. * 1000. ) ) ;
2017-11-20 01:14:18 +00:00
}
2017-10-13 01:36:59 +00:00
else
{
2017-10-28 19:50:06 +00:00
const auto m = int64_t ( ns / ( 1000ll * 1000 * 1000 * 60 ) ) ;
const auto s = int64_t ( ns - m * ( 1000ll * 1000 * 1000 * 60 ) ) ;
sprintf ( buf , " %s% " PRIi64 " :%04.1f " , sign , m , s / ( 1000. * 1000. * 1000. ) ) ;
2017-10-13 01:36:59 +00:00
}
2017-10-22 15:47:40 +00:00
return buf ;
2017-10-13 01:36:59 +00:00
}
2018-02-28 14:38:32 +00:00
static const char * TimeToStringInteger ( int64_t ns )
{
enum { Pool = 8 } ;
static char bufpool [ Pool ] [ 64 ] ;
static int bufsel = 0 ;
char * buf = bufpool [ bufsel ] ;
bufsel = ( bufsel + 1 ) % Pool ;
const char * sign = " " ;
if ( ns < 0 )
{
sign = " - " ;
ns = - ns ;
}
if ( ns < 1000 )
{
sprintf ( buf , " %s% " PRIi64 " ns " , sign , ns ) ;
}
else if ( ns < 1000ll * 1000 )
{
sprintf ( buf , " %s%.0f us " , sign , ns / 1000. ) ;
}
else if ( ns < 1000ll * 1000 * 1000 )
{
sprintf ( buf , " %s%.0f ms " , sign , ns / ( 1000. * 1000. ) ) ;
}
else if ( ns < 1000ll * 1000 * 1000 * 60 )
{
sprintf ( buf , " %s%.0f s " , sign , ns / ( 1000. * 1000. * 1000. ) ) ;
}
else
{
const auto m = int64_t ( ns / ( 1000ll * 1000 * 1000 * 60 ) ) ;
const auto s = int64_t ( ns - m * ( 1000ll * 1000 * 1000 * 60 ) ) ;
sprintf ( buf , " %s% " PRIi64 " :%02.0f " , sign , m , s / ( 1000. * 1000. * 1000. ) ) ;
}
return buf ;
}
2017-10-22 15:47:40 +00:00
static const char * RealToString ( double val , bool separator )
2017-10-13 01:36:59 +00:00
{
2017-10-22 15:47:40 +00:00
enum { Pool = 8 } ;
static char bufpool [ Pool ] [ 64 ] ;
static int bufsel = 0 ;
char * buf = bufpool [ bufsel ] ;
bufsel = ( bufsel + 1 ) % Pool ;
2017-10-13 01:36:59 +00:00
2017-10-22 15:47:40 +00:00
sprintf ( buf , " %f " , val ) ;
auto ptr = buf ;
if ( * ptr = = ' - ' ) ptr + + ;
2017-11-10 18:41:37 +00:00
2017-10-22 15:47:40 +00:00
const auto vbegin = ptr ;
if ( separator )
2017-10-13 01:36:59 +00:00
{
2017-10-22 15:47:40 +00:00
while ( * ptr ! = ' \0 ' & & * ptr ! = ' , ' & & * ptr ! = ' . ' ) ptr + + ;
auto end = ptr ;
while ( * end ! = ' \0 ' ) end + + ;
auto sz = end - ptr ;
while ( ptr - vbegin > 3 )
2017-10-13 01:36:59 +00:00
{
2017-10-22 15:47:40 +00:00
ptr - = 3 ;
memmove ( ptr + 1 , ptr , sz ) ;
* ptr = ' , ' ;
sz + = 4 ;
2017-10-13 01:36:59 +00:00
}
2017-10-19 21:26:21 +00:00
}
2017-10-22 15:47:40 +00:00
while ( * ptr ! = ' \0 ' & & * ptr ! = ' , ' & & * ptr ! = ' . ' ) ptr + + ;
2017-09-18 19:26:22 +00:00
2017-10-22 15:47:40 +00:00
if ( * ptr = = ' \0 ' ) return buf ;
while ( * ptr ! = ' \0 ' ) ptr + + ;
ptr - - ;
while ( * ptr = = ' 0 ' & & * ptr ! = ' , ' & & * ptr ! = ' . ' ) ptr - - ;
if ( * ptr ! = ' . ' & & * ptr ! = ' , ' ) ptr + + ;
* ptr = ' \0 ' ;
return buf ;
2017-09-20 20:34:56 +00:00
}
2017-09-18 00:22:59 +00:00
2017-10-06 16:25:30 +00:00
enum { MinVisSize = 3 } ;
2017-09-23 13:39:39 +00:00
2017-09-12 23:33:50 +00:00
static View * s_instance = nullptr ;
2017-11-11 21:56:05 +00:00
2017-09-12 23:33:50 +00:00
View : : View ( const char * addr )
2018-02-13 13:57:47 +00:00
: m_worker ( addr )
2017-09-30 14:58:02 +00:00
, m_staticView ( false )
2017-09-18 00:37:25 +00:00
, m_frameScale ( 0 )
2017-09-18 22:26:40 +00:00
, m_pause ( false )
, m_frameStart ( 0 )
2017-09-20 19:21:21 +00:00
, m_zvStart ( 0 )
, m_zvEnd ( 0 )
2017-10-12 20:27:17 +00:00
, m_zvHeight ( 0 )
, m_zvScroll ( 0 )
2017-09-29 19:49:14 +00:00
, m_zoneInfoWindow ( nullptr )
2017-10-08 21:03:38 +00:00
, m_lockHighlight { - 1 }
2017-11-12 00:25:44 +00:00
, m_gpuInfoWindow ( nullptr )
2017-11-15 23:33:10 +00:00
, m_gpuThread ( 0 )
, m_gpuStart ( 0 )
, m_gpuEnd ( 0 )
2017-10-13 11:32:23 +00:00
, m_showOptions ( false )
2017-10-14 12:36:30 +00:00
, m_showMessages ( false )
2018-03-24 13:40:48 +00:00
, m_showStatistics ( false )
2017-11-11 21:56:05 +00:00
, m_drawGpuZones ( true )
2017-10-13 11:32:23 +00:00
, m_drawZones ( true )
, m_drawLocks ( true )
2017-10-13 12:54:32 +00:00
, m_drawPlots ( true )
2017-10-22 11:32:27 +00:00
, m_onlyContendedLocks ( false )
2017-10-22 11:56:05 +00:00
, m_namespace ( Namespace : : Full )
2017-09-21 00:10:20 +00:00
{
2017-09-12 23:33:50 +00:00
assert ( s_instance = = nullptr ) ;
s_instance = this ;
2017-09-21 00:10:20 +00:00
2017-09-19 22:46:30 +00:00
ImGuiStyle & style = ImGui : : GetStyle ( ) ;
style . FrameRounding = 2.f ;
2017-11-11 00:39:34 +00:00
}
2018-02-13 13:57:47 +00:00
View : : View ( FileRead & f )
: m_worker ( f )
, m_staticView ( true )
, m_frameScale ( 0 )
, m_pause ( false )
, m_frameStart ( 0 )
, m_zvStart ( 0 )
, m_zvEnd ( 0 )
, m_zvHeight ( 0 )
, m_zvScroll ( 0 )
, m_zoneInfoWindow ( nullptr )
, m_gpuInfoWindow ( nullptr )
, m_gpuThread ( 0 )
, m_gpuStart ( 0 )
, m_gpuEnd ( 0 )
, m_showOptions ( false )
, m_showMessages ( false )
, m_drawGpuZones ( true )
, m_drawZones ( true )
, m_drawLocks ( true )
, m_drawPlots ( true )
, m_onlyContendedLocks ( false )
2018-03-24 16:28:10 +00:00
, m_statSort ( 0 )
2018-02-13 13:57:47 +00:00
, m_namespace ( Namespace : : Full )
2017-11-14 22:37:44 +00:00
{
2018-02-13 13:57:47 +00:00
assert ( s_instance = = nullptr ) ;
s_instance = this ;
2017-11-14 22:37:44 +00:00
}
2018-02-13 13:57:47 +00:00
View : : ~ View ( )
2017-09-21 23:30:57 +00:00
{
2018-02-13 13:57:47 +00:00
m_worker . Shutdown ( ) ;
2017-09-21 23:30:57 +00:00
2018-02-13 13:57:47 +00:00
assert ( s_instance ! = nullptr ) ;
s_instance = nullptr ;
2017-09-26 16:54:48 +00:00
}
2017-10-22 11:56:05 +00:00
const char * View : : ShortenNamespace ( const char * name ) const
{
if ( m_namespace = = Namespace : : Full ) return name ;
if ( m_namespace = = Namespace : : Short )
{
auto ptr = name ;
while ( * ptr ! = ' \0 ' ) ptr + + ;
while ( ptr > name & & * ptr ! = ' : ' ) ptr - - ;
if ( * ptr = = ' : ' ) ptr + + ;
return ptr ;
}
static char buf [ 1024 ] ;
auto dst = buf ;
auto ptr = name ;
for ( ; ; )
{
auto start = ptr ;
while ( * ptr ! = ' \0 ' & & * ptr ! = ' : ' ) ptr + + ;
if ( * ptr = = ' \0 ' )
{
memcpy ( dst , start , ptr - start + 1 ) ;
return buf ;
}
* dst + + = * start ;
* dst + + = ' : ' ;
while ( * ptr = = ' : ' ) ptr + + ;
}
}
2018-01-17 11:49:50 +00:00
void View : : DrawHelpMarker ( const char * desc ) const
{
ImGui : : TextDisabled ( " (?) " ) ;
2018-03-24 13:42:48 +00:00
if ( ImGui : : IsItemHovered ( ) )
2018-01-17 11:49:50 +00:00
{
ImGui : : BeginTooltip ( ) ;
ImGui : : PushTextWrapPos ( 450.0f ) ;
ImGui : : TextUnformatted ( desc ) ;
ImGui : : PopTextWrapPos ( ) ;
ImGui : : EndTooltip ( ) ;
}
}
2017-11-25 14:45:16 +00:00
void View : : DrawTextContrast ( ImDrawList * draw , const ImVec2 & pos , uint32_t color , const char * text )
{
draw - > AddText ( pos + ImVec2 ( 1 , 1 ) , 0x88000000 , text ) ;
draw - > AddText ( pos , color , text ) ;
}
2017-09-15 00:30:22 +00:00
void View : : Draw ( )
{
s_instance - > DrawImpl ( ) ;
}
void View : : DrawImpl ( )
{
2018-02-13 13:57:47 +00:00
if ( ! m_worker . HasData ( ) )
2017-09-20 18:38:12 +00:00
{
2018-02-13 13:57:47 +00:00
ImGui : : Begin ( m_worker . GetAddr ( ) . c_str ( ) , nullptr , ImGuiWindowFlags_AlwaysAutoResize ) ;
2017-09-20 18:38:12 +00:00
ImGui : : Text ( " Waiting for connection... " ) ;
ImGui : : End ( ) ;
return ;
}
2017-09-30 14:58:02 +00:00
if ( ! m_staticView )
{
DrawConnection ( ) ;
}
2017-09-30 12:37:21 +00:00
2018-03-24 22:43:51 +00:00
const auto th = ImGui : : GetTextLineHeight ( ) ;
const auto bw = 4.7f * th ;
2018-02-13 13:57:47 +00:00
std : : lock_guard < NonRecursiveBenaphore > lock ( m_worker . GetDataLock ( ) ) ;
2018-03-24 21:07:41 +00:00
ImGui : : Begin ( m_worker . GetCaptureName ( ) . c_str ( ) , nullptr , ImVec2 ( 1550 , 800 ) , - 1 , ImGuiWindowFlags_NoScrollbar ) ;
2018-03-24 13:45:01 +00:00
if ( ! m_worker . IsDataStatic ( ) )
{
2018-03-24 22:43:51 +00:00
if ( ImGui : : Button ( m_pause ? " Resume " : " Pause " , ImVec2 ( bw , 0 ) ) ) m_pause = ! m_pause ;
2018-03-24 13:45:01 +00:00
ImGui : : SameLine ( ) ;
}
2018-03-24 22:43:51 +00:00
if ( ImGui : : Button ( " Options " , ImVec2 ( bw , 0 ) ) ) m_showOptions = true ;
2017-09-30 12:37:21 +00:00
ImGui : : SameLine ( ) ;
2018-03-24 22:43:51 +00:00
if ( ImGui : : Button ( " Messages " , ImVec2 ( bw , 0 ) ) ) m_showMessages = true ;
2017-10-14 12:36:30 +00:00
ImGui : : SameLine ( ) ;
2018-03-24 22:43:51 +00:00
if ( ImGui : : Button ( " Find Zone " , ImVec2 ( bw , 0 ) ) ) m_findZone . show = true ;
2018-03-24 13:40:48 +00:00
ImGui : : SameLine ( ) ;
2018-03-24 22:43:51 +00:00
if ( ImGui : : Button ( " Statistics " , ImVec2 ( bw , 0 ) ) ) m_showStatistics = true ;
2018-01-17 11:49:50 +00:00
ImGui : : SameLine ( ) ;
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " Frames: %-7 " PRIu64 " Time span: %-10s View span: %-10s Zones: %-13s Queue delay: %s Timer resolution: %s " , m_worker . GetFrameCount ( ) , TimeToString ( m_worker . GetLastTime ( ) - m_worker . GetFrameBegin ( 0 ) ) , TimeToString ( m_zvEnd - m_zvStart ) , RealToString ( m_worker . GetZoneCount ( ) , true ) , TimeToString ( m_worker . GetDelay ( ) ) , TimeToString ( m_worker . GetResolution ( ) ) ) ;
2017-09-30 12:37:21 +00:00
DrawFrames ( ) ;
DrawZones ( ) ;
ImGui : : End ( ) ;
m_zoneHighlight = nullptr ;
2017-11-12 00:28:07 +00:00
m_gpuHighlight = nullptr ;
2017-11-12 00:25:44 +00:00
DrawInfoWindow ( ) ;
2017-11-12 00:28:07 +00:00
2017-10-13 11:32:23 +00:00
if ( m_showOptions ) DrawOptions ( ) ;
2017-10-14 12:36:30 +00:00
if ( m_showMessages ) DrawMessages ( ) ;
2018-01-17 11:49:50 +00:00
if ( m_findZone . show ) DrawFindZone ( ) ;
2018-03-24 13:40:48 +00:00
if ( m_showStatistics ) DrawStatistics ( ) ;
2017-09-30 12:37:21 +00:00
2017-11-27 21:41:30 +00:00
if ( m_zoomAnim . active )
2017-09-30 12:37:21 +00:00
{
2017-11-27 21:41:30 +00:00
const auto & io = ImGui : : GetIO ( ) ;
m_zoomAnim . progress + = io . DeltaTime * m_zoomAnim . lenMod ;
if ( m_zoomAnim . progress > = 1.f )
{
m_zoomAnim . active = false ;
m_zvStart = m_zoomAnim . start1 ;
m_zvEnd = m_zoomAnim . end1 ;
}
else
{
const auto v = sqrt ( sin ( M_PI_2 * m_zoomAnim . progress ) ) ;
m_zvStart = int64_t ( m_zoomAnim . start0 + ( m_zoomAnim . start1 - m_zoomAnim . start0 ) * v ) ;
m_zvEnd = int64_t ( m_zoomAnim . end0 + ( m_zoomAnim . end1 - m_zoomAnim . end0 ) * v ) ;
}
2017-09-30 12:37:21 +00:00
}
}
void View : : DrawConnection ( )
{
2017-10-18 21:25:35 +00:00
const auto ty = ImGui : : GetFontSize ( ) ;
const auto cs = ty * 0.9f ;
2017-09-15 00:30:22 +00:00
{
2018-02-13 13:57:47 +00:00
std : : lock_guard < NonRecursiveBenaphore > lock ( m_worker . GetMbpsDataLock ( ) ) ;
ImGui : : Begin ( m_worker . GetAddr ( ) . c_str ( ) , nullptr , ImGuiWindowFlags_AlwaysAutoResize ) ;
const auto & mbpsVector = m_worker . GetMbpsData ( ) ;
const auto mbps = mbpsVector . back ( ) ;
2017-09-15 00:30:22 +00:00
char buf [ 64 ] ;
if ( mbps < 0.1f )
{
2017-09-16 23:41:18 +00:00
sprintf ( buf , " %6.2f Kbps " , mbps * 1000.f ) ;
2017-09-15 00:30:22 +00:00
}
else
{
2017-09-16 23:41:18 +00:00
sprintf ( buf , " %6.2f Mbps " , mbps ) ;
2017-09-15 00:30:22 +00:00
}
2017-10-18 21:25:35 +00:00
ImGui : : Dummy ( ImVec2 ( cs , 0 ) ) ;
2017-09-17 22:31:38 +00:00
ImGui : : SameLine ( ) ;
2018-02-13 13:57:47 +00:00
ImGui : : PlotLines ( buf , mbpsVector . data ( ) , mbpsVector . size ( ) , 0 , nullptr , 0 , std : : numeric_limits < float > : : max ( ) , ImVec2 ( 150 , 0 ) ) ;
ImGui : : Text ( " Ratio %.1f%% Real: %6.2f Mbps " , m_worker . GetCompRatio ( ) * 100.f , mbps / m_worker . GetCompRatio ( ) ) ;
2017-09-15 00:30:22 +00:00
}
2017-09-15 18:31:59 +00:00
2017-09-16 23:22:46 +00:00
ImGui : : Text ( " Memory usage: %.2f MB " , memUsage . load ( std : : memory_order_relaxed ) / ( 1024.f * 1024.f ) ) ;
2017-09-17 22:31:38 +00:00
const auto wpos = ImGui : : GetWindowPos ( ) + ImGui : : GetWindowContentRegionMin ( ) ;
2018-02-13 13:57:47 +00:00
ImGui : : GetWindowDrawList ( ) - > AddCircleFilled ( wpos + ImVec2 ( 1 + cs * 0.5 , 3 + ty * 0.5 ) , cs * 0.5 , m_worker . IsConnected ( ) ? 0xFF2222CC : 0xFF444444 , 10 ) ;
2017-09-17 22:31:38 +00:00
2018-02-13 13:57:47 +00:00
std : : lock_guard < NonRecursiveBenaphore > lock ( m_worker . GetDataLock ( ) ) ;
2017-09-15 22:57:50 +00:00
{
2018-02-13 13:57:47 +00:00
const auto sz = m_worker . GetFrameCount ( ) ;
2017-09-15 22:57:50 +00:00
if ( sz > 1 )
{
2018-02-13 13:57:47 +00:00
const auto dt = m_worker . GetFrameTime ( sz - 2 ) ;
2017-09-15 22:57:50 +00:00
const auto dtm = dt / 1000000.f ;
const auto fps = 1000.f / dtm ;
2017-09-16 23:41:18 +00:00
ImGui : : Text ( " FPS: %6.1f Frame time: %.2f ms " , fps , dtm ) ;
2017-09-15 22:57:50 +00:00
}
}
2017-09-18 00:37:25 +00:00
2017-09-30 12:56:09 +00:00
if ( ImGui : : Button ( " Save trace " ) )
{
# ifdef TRACY_FILESELECTOR
nfdchar_t * fn ;
auto res = NFD_SaveDialog ( " tracy " , nullptr , & fn ) ;
if ( res = = NFD_OKAY )
# else
const char * fn = " trace.tracy " ;
# endif
{
2017-10-12 20:38:11 +00:00
std : : unique_ptr < FileWrite > f ;
const auto sz = strlen ( fn ) ;
if ( sz < 7 | | memcmp ( fn + sz - 6 , " .tracy " , 6 ) ! = 0 )
{
char tmp [ 1024 ] ;
sprintf ( tmp , " %s.tracy " , fn ) ;
f . reset ( FileWrite : : Open ( tmp ) ) ;
}
else
{
f . reset ( FileWrite : : Open ( fn ) ) ;
}
2017-09-30 14:20:08 +00:00
if ( f )
{
2018-02-13 13:57:47 +00:00
m_worker . Write ( * f ) ;
2017-09-30 14:20:08 +00:00
}
2017-09-30 12:56:09 +00:00
}
}
2017-09-18 00:37:25 +00:00
ImGui : : End ( ) ;
}
static ImU32 GetFrameColor ( uint64_t frameTime )
{
enum { BestTime = 1000 * 1000 * 1000 / 143 } ;
enum { GoodTime = 1000 * 1000 * 1000 / 59 } ;
enum { BadTime = 1000 * 1000 * 1000 / 29 } ;
2017-09-18 17:03:29 +00:00
return frameTime > BadTime ? 0xFF2222DD :
frameTime > GoodTime ? 0xFF22DDDD :
frameTime > BestTime ? 0xFF22DD22 : 0xFFDD9900 ;
2017-09-18 00:37:25 +00:00
}
2017-09-19 22:05:45 +00:00
static int GetFrameWidth ( int frameScale )
{
return frameScale = = 0 ? 4 : ( frameScale = = - 1 ? 6 : 1 ) ;
}
static int GetFrameGroup ( int frameScale )
{
return frameScale < 2 ? 1 : ( 1 < < ( frameScale - 1 ) ) ;
}
2017-09-18 00:37:25 +00:00
void View : : DrawFrames ( )
{
2018-02-13 13:57:47 +00:00
assert ( m_worker . GetFrameCount ( ) ! = 0 ) ;
2017-09-20 19:21:21 +00:00
2017-09-18 00:37:25 +00:00
enum { Height = 40 } ;
enum { MaxFrameTime = 50 * 1000 * 1000 } ; // 50ms
ImGuiWindow * window = ImGui : : GetCurrentWindow ( ) ;
if ( window - > SkipItems ) return ;
2017-09-18 23:24:31 +00:00
auto & io = ImGui : : GetIO ( ) ;
2017-09-20 00:19:39 +00:00
const auto wpos = ImGui : : GetCursorScreenPos ( ) ;
2017-09-18 00:37:25 +00:00
const auto wspace = ImGui : : GetWindowContentRegionMax ( ) - ImGui : : GetWindowContentRegionMin ( ) ;
const auto w = wspace . x ;
auto draw = ImGui : : GetWindowDrawList ( ) ;
2017-09-20 00:19:39 +00:00
ImGui : : InvisibleButton ( " ##frames " , ImVec2 ( w , Height ) ) ;
bool hover = ImGui : : IsItemHovered ( ) ;
2017-09-18 00:37:25 +00:00
draw - > AddRectFilled ( wpos , wpos + ImVec2 ( w , Height ) , 0x33FFFFFF ) ;
2017-09-19 22:08:15 +00:00
const auto wheel = io . MouseWheel ;
const auto prevScale = m_frameScale ;
2017-09-18 20:12:39 +00:00
if ( hover )
2017-09-18 00:37:25 +00:00
{
if ( wheel > 0 )
{
2017-09-19 19:10:11 +00:00
if ( m_frameScale > - 1 ) m_frameScale - - ;
2017-09-18 00:37:25 +00:00
}
else if ( wheel < 0 )
{
if ( m_frameScale < 10 ) m_frameScale + + ;
}
}
2017-09-18 19:26:22 +00:00
2017-09-19 22:05:45 +00:00
const int fwidth = GetFrameWidth ( m_frameScale ) ;
const int group = GetFrameGroup ( m_frameScale ) ;
2018-02-13 13:57:47 +00:00
const int total = m_worker . GetFrameCount ( ) ;
2017-09-18 23:24:14 +00:00
const int onScreen = ( w - 2 ) / fwidth ;
2017-09-20 19:21:21 +00:00
if ( ! m_pause )
{
m_frameStart = ( total < onScreen * group ) ? 0 : total - onScreen * group ;
2018-02-13 13:57:47 +00:00
m_zvStart = m_worker . GetFrameBegin ( std : : max ( 0 , total - 4 ) ) ;
if ( total = = 1 )
2017-09-23 12:45:38 +00:00
{
2018-02-13 13:57:47 +00:00
m_zvEnd = m_worker . GetLastTime ( ) ;
2017-09-23 12:45:38 +00:00
}
else
{
2018-02-13 13:57:47 +00:00
m_zvEnd = m_worker . GetFrameBegin ( total - 1 ) ;
2017-09-23 12:45:38 +00:00
}
2017-09-20 19:21:21 +00:00
}
2017-09-18 19:26:22 +00:00
2017-09-19 19:10:31 +00:00
if ( hover )
2017-09-18 23:24:31 +00:00
{
2017-09-19 19:10:31 +00:00
if ( ImGui : : IsMouseDragging ( 1 , 0 ) )
{
m_pause = true ;
const auto delta = ImGui : : GetMouseDragDelta ( 1 , 0 ) . x ;
if ( abs ( delta ) > = fwidth )
{
const auto d = ( int ) delta / fwidth ;
m_frameStart = std : : max ( 0 , m_frameStart - d * group ) ;
io . MouseClickedPos [ 1 ] . x = io . MousePos . x + d * fwidth - delta ;
}
}
const auto mx = io . MousePos . x ;
if ( mx > wpos . x & & mx < wpos . x + w - 1 )
2017-09-18 23:24:31 +00:00
{
2017-09-19 19:10:31 +00:00
const auto mo = mx - ( wpos . x + 1 ) ;
const auto off = mo * group / fwidth ;
2017-09-19 22:08:15 +00:00
const int sel = m_frameStart + off ;
if ( sel < total )
{
2017-09-19 19:10:31 +00:00
ImGui : : BeginTooltip ( ) ;
if ( group > 1 )
{
2018-02-13 13:57:47 +00:00
auto f = m_worker . GetFrameTime ( sel ) ;
2017-09-19 19:10:31 +00:00
auto g = std : : min ( group , total - sel ) ;
for ( int j = 1 ; j < g ; j + + )
{
2018-02-13 13:57:47 +00:00
f = std : : max ( f , m_worker . GetFrameTime ( sel + j ) ) ;
2017-09-19 19:10:31 +00:00
}
ImGui : : Text ( " Frames: %i - %i (%i) " , sel , sel + g - 1 , g ) ;
2017-11-17 23:51:04 +00:00
ImGui : : Separator ( ) ;
2017-09-19 19:10:31 +00:00
ImGui : : Text ( " Max frame time: %s " , TimeToString ( f ) ) ;
}
else
{
2017-10-16 23:17:55 +00:00
if ( sel = = 0 )
{
2017-10-28 19:50:06 +00:00
ImGui : : Text ( " Tracy initialization " ) ;
2017-11-17 23:51:04 +00:00
ImGui : : Separator ( ) ;
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " Time: %s " , TimeToString ( m_worker . GetFrameTime ( sel ) ) ) ;
2017-10-16 23:17:55 +00:00
}
else
{
ImGui : : Text ( " Frame: %i " , sel ) ;
2017-11-17 23:51:04 +00:00
ImGui : : Separator ( ) ;
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " Frame time: %s " , TimeToString ( m_worker . GetFrameTime ( sel ) ) ) ;
2017-10-16 23:17:55 +00:00
}
2017-09-19 19:10:31 +00:00
}
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " Time from start of program: %s " , TimeToString ( m_worker . GetFrameBegin ( sel ) - m_worker . GetFrameBegin ( 0 ) ) ) ;
2017-09-19 19:10:31 +00:00
ImGui : : EndTooltip ( ) ;
2017-09-22 22:46:15 +00:00
if ( ImGui : : IsMouseClicked ( 0 ) )
{
m_pause = true ;
2018-02-13 13:57:47 +00:00
m_zvStart = m_worker . GetFrameBegin ( sel ) ;
m_zvEnd = m_worker . GetFrameEnd ( sel + group - 1 ) ;
2017-09-22 22:46:15 +00:00
if ( m_zvStart = = m_zvEnd ) m_zvStart - - ;
}
else if ( ImGui : : IsMouseDragging ( 0 ) )
{
2018-02-13 13:57:47 +00:00
m_zvStart = std : : min ( m_zvStart , m_worker . GetFrameBegin ( sel ) ) ;
m_zvEnd = std : : max ( m_zvEnd , m_worker . GetFrameEnd ( sel + group - 1 ) ) ;
2017-09-22 22:46:15 +00:00
}
2017-09-19 19:10:31 +00:00
}
2017-09-19 22:08:15 +00:00
if ( m_pause & & wheel ! = 0 )
{
const int pfwidth = GetFrameWidth ( prevScale ) ;
const int pgroup = GetFrameGroup ( prevScale ) ;
const auto oldoff = mo * pgroup / pfwidth ;
m_frameStart = std : : min ( total , std : : max ( 0 , m_frameStart - int ( off - oldoff ) ) ) ;
}
2017-09-18 23:24:31 +00:00
}
}
2017-09-18 19:32:26 +00:00
int i = 0 , idx = 0 ;
2017-09-18 22:26:40 +00:00
while ( i < onScreen & & m_frameStart + idx < total )
2017-09-18 00:37:25 +00:00
{
2018-02-13 13:57:47 +00:00
auto f = m_worker . GetFrameTime ( m_frameStart + idx ) ;
2017-09-18 20:12:39 +00:00
int g ;
2017-09-18 19:32:26 +00:00
if ( group > 1 )
{
2017-09-18 22:26:40 +00:00
g = std : : min ( group , total - ( m_frameStart + idx ) ) ;
2017-09-18 19:32:26 +00:00
for ( int j = 1 ; j < g ; j + + )
{
2018-02-13 13:57:47 +00:00
f = std : : max ( f , m_worker . GetFrameTime ( m_frameStart + idx + j ) ) ;
2017-09-18 19:32:26 +00:00
}
}
2017-09-18 00:37:25 +00:00
const auto h = float ( std : : min < uint64_t > ( MaxFrameTime , f ) ) / MaxFrameTime * ( Height - 2 ) ;
if ( fwidth ! = 1 )
{
2017-09-19 19:10:31 +00:00
draw - > AddRectFilled ( wpos + ImVec2 ( 1 + i * fwidth , Height - 1 - h ) , wpos + ImVec2 ( fwidth + i * fwidth , Height - 1 ) , GetFrameColor ( f ) ) ;
2017-09-18 00:37:25 +00:00
}
else
{
draw - > AddLine ( wpos + ImVec2 ( 1 + i , Height - 2 - h ) , wpos + ImVec2 ( 1 + i , Height - 2 ) , GetFrameColor ( f ) ) ;
}
2017-09-19 19:10:31 +00:00
2017-09-18 19:26:22 +00:00
i + + ;
2017-09-18 19:32:26 +00:00
idx + = group ;
2017-09-18 00:37:25 +00:00
}
2017-09-20 19:21:29 +00:00
2018-02-13 13:57:47 +00:00
const std : : pair < int , int > zrange = m_worker . GetFrameRange ( m_zvStart , m_zvEnd ) ;
2017-09-20 19:21:29 +00:00
2018-02-13 13:57:47 +00:00
if ( zrange . second > m_frameStart & & zrange . first < m_frameStart + onScreen * group )
2017-09-20 19:21:29 +00:00
{
2018-02-13 13:57:47 +00:00
auto x1 = std : : min ( onScreen * fwidth , ( zrange . second - m_frameStart ) * fwidth / group ) ;
auto x0 = std : : max ( 0 , ( zrange . first - m_frameStart ) * fwidth / group ) ;
2017-09-20 19:21:29 +00:00
if ( x0 = = x1 ) x1 = x0 + 1 ;
draw - > AddRectFilled ( wpos + ImVec2 ( 1 + x0 , 0 ) , wpos + ImVec2 ( 1 + x1 , Height ) , 0x55DD22DD ) ;
}
2017-09-15 00:30:22 +00:00
}
2017-10-12 20:27:17 +00:00
void View : : HandleZoneViewMouse ( int64_t timespan , const ImVec2 & wpos , float w , double & pxns )
2017-09-20 22:57:26 +00:00
{
2017-10-15 14:42:56 +00:00
assert ( timespan > 0 ) ;
2017-10-12 20:27:17 +00:00
auto & io = ImGui : : GetIO ( ) ;
2017-09-20 22:57:26 +00:00
2017-10-15 14:42:56 +00:00
const auto nspx = double ( timespan ) / w ;
if ( ImGui : : IsMouseClicked ( 0 ) )
{
2018-03-04 21:21:35 +00:00
m_highlight . active = true ;
m_highlight . start = m_highlight . end = m_zvStart + ( io . MousePos . x - wpos . x ) * nspx ;
2017-10-15 14:42:56 +00:00
}
else if ( ImGui : : IsMouseDragging ( 0 , 0 ) )
{
2018-03-04 21:21:35 +00:00
m_highlight . end = m_zvStart + ( io . MousePos . x - wpos . x ) * nspx ;
2017-10-15 14:42:56 +00:00
}
else
{
2018-03-04 21:21:35 +00:00
m_highlight . active = false ;
2017-10-15 14:42:56 +00:00
}
2017-10-12 20:27:17 +00:00
if ( ImGui : : IsMouseDragging ( 1 , 0 ) )
{
m_pause = true ;
2017-10-15 14:20:45 +00:00
const auto delta = ImGui : : GetMouseDragDelta ( 1 , 0 ) ;
const auto dpx = int64_t ( delta . x * nspx ) ;
2017-10-12 20:27:17 +00:00
if ( dpx ! = 0 )
{
m_zvStart - = dpx ;
m_zvEnd - = dpx ;
io . MouseClickedPos [ 1 ] . x = io . MousePos . x ;
}
2017-10-15 14:20:45 +00:00
if ( delta . y ! = 0 )
{
auto y = ImGui : : GetScrollY ( ) ;
ImGui : : SetScrollY ( y - delta . y ) ;
io . MouseClickedPos [ 1 ] . y = io . MousePos . y ;
}
2017-10-12 20:27:17 +00:00
}
2017-09-20 22:57:26 +00:00
2017-10-12 20:27:17 +00:00
const auto wheel = io . MouseWheel ;
if ( wheel ! = 0 )
{
m_pause = true ;
const double mouse = io . MousePos . x - wpos . x ;
const auto p = mouse / w ;
const auto p1 = timespan * p ;
const auto p2 = timespan - p1 ;
if ( wheel > 0 )
{
2017-11-06 00:04:49 +00:00
m_zvStart + = int64_t ( p1 * 0.25 ) ;
m_zvEnd - = int64_t ( p2 * 0.25 ) ;
2017-10-12 20:27:17 +00:00
}
2017-10-28 19:50:06 +00:00
else if ( timespan < 1000ll * 1000 * 1000 * 60 )
2017-10-12 20:27:17 +00:00
{
2017-11-06 00:04:49 +00:00
m_zvStart - = std : : max ( int64_t ( 1 ) , int64_t ( p1 * 0.25 ) ) ;
m_zvEnd + = std : : max ( int64_t ( 1 ) , int64_t ( p2 * 0.25 ) ) ;
2017-10-12 20:27:17 +00:00
}
timespan = m_zvEnd - m_zvStart ;
pxns = w / double ( timespan ) ;
}
}
2017-10-22 15:48:01 +00:00
static const char * GetFrameText ( int i , uint64_t ftime )
{
static char buf [ 128 ] ;
if ( i = = 0 )
{
sprintf ( buf , " Tracy init (%s) " , TimeToString ( ftime ) ) ;
}
else
{
sprintf ( buf , " Frame %i (%s) " , i , TimeToString ( ftime ) ) ;
}
return buf ;
}
2017-10-13 13:26:18 +00:00
bool View : : DrawZoneFrames ( )
2017-10-12 20:27:17 +00:00
{
2017-09-20 22:57:26 +00:00
const auto wpos = ImGui : : GetCursorScreenPos ( ) ;
2017-10-12 20:27:17 +00:00
const auto w = ImGui : : GetWindowContentRegionWidth ( ) - ImGui : : GetStyle ( ) . ScrollbarSize ;
const auto h = ImGui : : GetFontSize ( ) ;
const auto wh = ImGui : : GetContentRegionAvail ( ) . y ;
2017-09-20 22:57:26 +00:00
auto draw = ImGui : : GetWindowDrawList ( ) ;
2017-10-22 15:48:01 +00:00
const auto ty = ImGui : : GetFontSize ( ) ;
2017-11-26 01:18:17 +00:00
const auto fy = round ( h * 1.5 ) ;
2017-09-20 22:57:26 +00:00
2017-11-26 01:18:17 +00:00
ImGui : : InvisibleButton ( " ##zoneFrames " , ImVec2 ( w , h * 2.5 ) ) ;
2017-09-20 22:57:26 +00:00
bool hover = ImGui : : IsItemHovered ( ) ;
2017-09-20 23:39:07 +00:00
auto timespan = m_zvEnd - m_zvStart ;
auto pxns = w / double ( timespan ) ;
2017-09-20 22:57:26 +00:00
2017-10-12 20:27:17 +00:00
if ( hover ) HandleZoneViewMouse ( timespan , wpos , w , pxns ) ;
2017-09-20 23:13:23 +00:00
2017-11-26 01:18:17 +00:00
{
const auto nspx = 1.0 / pxns ;
const auto scale = std : : max ( 0.0 , round ( log10 ( nspx ) + 2 ) ) ;
const auto step = pow ( 10 , scale ) ;
const auto dx = step * pxns ;
double x = 0 ;
int tw = 0 ;
int tx = 0 ;
int64_t tt = 0 ;
while ( x < w )
{
draw - > AddLine ( wpos + ImVec2 ( x , 0 ) , wpos + ImVec2 ( x , round ( ty * 0.5 ) ) , 0x66FFFFFF ) ;
if ( tw = = 0 )
{
char buf [ 128 ] ;
2018-02-13 13:57:47 +00:00
const auto t = m_zvStart - m_worker . GetFrameBegin ( 0 ) ;
2017-11-26 01:24:13 +00:00
auto txt = TimeToString ( t ) ;
if ( t > = 0 )
{
sprintf ( buf , " +%s " , txt ) ;
txt = buf ;
}
draw - > AddText ( wpos + ImVec2 ( x , round ( ty * 0.5 ) ) , 0x66FFFFFF , txt ) ;
tw = ImGui : : CalcTextSize ( txt ) . x ;
2017-11-26 01:18:17 +00:00
}
else if ( x > tx + tw + ty * 2 )
{
tx = x ;
auto txt = TimeToString ( tt ) ;
draw - > AddText ( wpos + ImVec2 ( x , round ( ty * 0.5 ) ) , 0x66FFFFFF , txt ) ;
tw = ImGui : : CalcTextSize ( txt ) . x ;
}
for ( int i = 1 ; i < 5 ; i + + )
{
draw - > AddLine ( wpos + ImVec2 ( x + i * dx / 10 , 0 ) , wpos + ImVec2 ( x + i * dx / 10 , round ( ty * 0.25 ) ) , 0x33FFFFFF ) ;
}
draw - > AddLine ( wpos + ImVec2 ( x + 5 * dx / 10 , 0 ) , wpos + ImVec2 ( x + 5 * dx / 10 , round ( ty * 0.375 ) ) , 0x33FFFFFF ) ;
for ( int i = 6 ; i < 10 ; i + + )
{
draw - > AddLine ( wpos + ImVec2 ( x + i * dx / 10 , 0 ) , wpos + ImVec2 ( x + i * dx / 10 , round ( ty * 0.25 ) ) , 0x33FFFFFF ) ;
}
x + = dx ;
tt + = step ;
}
}
2018-02-13 13:57:47 +00:00
const std : : pair < int , int > zrange = m_worker . GetFrameRange ( m_zvStart , m_zvEnd ) ;
if ( zrange . first = = - 1 ) return hover ;
2017-09-20 22:57:26 +00:00
2018-02-13 13:57:47 +00:00
for ( int i = zrange . first ; i < zrange . second ; i + + )
2017-10-22 15:48:01 +00:00
{
2018-02-13 13:57:47 +00:00
const auto ftime = m_worker . GetFrameTime ( i ) ;
const auto fbegin = m_worker . GetFrameBegin ( i ) ;
const auto fend = m_worker . GetFrameEnd ( i ) ;
2017-10-22 15:48:01 +00:00
const auto fsz = pxns * ftime ;
2017-11-26 01:18:17 +00:00
if ( hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( ( fbegin - m_zvStart ) * pxns , fy ) , wpos + ImVec2 ( ( fend - m_zvStart ) * pxns , fy + ty ) ) )
2017-09-20 23:18:24 +00:00
{
2017-10-22 15:48:01 +00:00
ImGui : : BeginTooltip ( ) ;
ImGui : : Text ( " %s " , GetFrameText ( i , ftime ) ) ;
2017-11-17 23:51:04 +00:00
ImGui : : Separator ( ) ;
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " Time from start of program: %s " , TimeToString ( m_worker . GetFrameBegin ( i ) - m_worker . GetFrameBegin ( 0 ) ) ) ;
2017-10-22 15:48:01 +00:00
ImGui : : EndTooltip ( ) ;
2017-09-20 23:18:24 +00:00
2017-10-22 15:48:01 +00:00
if ( ImGui : : IsMouseClicked ( 2 ) )
2017-10-16 23:17:55 +00:00
{
2017-11-27 21:12:26 +00:00
ZoomToRange ( fbegin , fend ) ;
2017-10-22 15:48:01 +00:00
m_pause = true ;
2017-10-16 23:17:55 +00:00
}
2017-10-22 15:48:01 +00:00
}
if ( fsz < = 4 ) continue ;
if ( fbegin > = m_zvStart )
{
draw - > AddLine ( wpos + ImVec2 ( ( fbegin - m_zvStart ) * pxns , 0 ) , wpos + ImVec2 ( ( fbegin - m_zvStart ) * pxns , wh ) , 0x22FFFFFF ) ;
}
if ( fsz > = 5 )
{
auto buf = GetFrameText ( i , ftime ) ;
2017-10-28 19:55:01 +00:00
auto tx = ImGui : : CalcTextSize ( buf ) . x ;
2017-10-22 15:48:01 +00:00
uint32_t color = i = = 0 ? 0xFF4444FF : 0xFFFFFFFF ;
2017-10-28 19:55:01 +00:00
if ( fsz - 5 < = tx )
{
buf = TimeToString ( ftime ) ;
tx = ImGui : : CalcTextSize ( buf ) . x ;
}
2017-10-22 15:48:01 +00:00
if ( fbegin > = m_zvStart )
2017-10-16 23:17:55 +00:00
{
2017-11-26 01:18:17 +00:00
draw - > AddLine ( wpos + ImVec2 ( ( fbegin - m_zvStart ) * pxns + 2 , fy + 1 ) , wpos + ImVec2 ( ( fbegin - m_zvStart ) * pxns + 2 , fy + ty - 1 ) , color ) ;
2017-10-16 23:17:55 +00:00
}
2017-10-22 15:48:01 +00:00
if ( fend < = m_zvEnd )
2017-09-20 22:57:26 +00:00
{
2017-11-26 01:18:17 +00:00
draw - > AddLine ( wpos + ImVec2 ( ( fend - m_zvStart ) * pxns - 2 , fy + 1 ) , wpos + ImVec2 ( ( fend - m_zvStart ) * pxns - 2 , fy + ty - 1 ) , color ) ;
2017-09-20 22:57:26 +00:00
}
2017-10-22 15:48:01 +00:00
if ( fsz - 5 > tx )
2017-09-20 22:57:26 +00:00
{
2017-10-22 15:48:01 +00:00
const auto part = ( fsz - 5 - tx ) / 2 ;
2017-11-26 01:18:17 +00:00
draw - > AddLine ( wpos + ImVec2 ( std : : max ( - 10.0 , ( fbegin - m_zvStart ) * pxns + 2 ) , fy + round ( ty / 2 ) ) , wpos + ImVec2 ( std : : min ( w + 20.0 , ( fbegin - m_zvStart ) * pxns + part ) , fy + round ( ty / 2 ) ) , color ) ;
draw - > AddText ( wpos + ImVec2 ( ( fbegin - m_zvStart ) * pxns + 2 + part , fy ) , color , buf ) ;
draw - > AddLine ( wpos + ImVec2 ( std : : max ( - 10.0 , ( fbegin - m_zvStart ) * pxns + 2 + part + tx ) , fy + round ( ty / 2 ) ) , wpos + ImVec2 ( std : : min ( w + 20.0 , ( fend - m_zvStart ) * pxns - 2 ) , fy + round ( ty / 2 ) ) , color ) ;
2017-09-20 22:57:26 +00:00
}
2017-10-22 15:48:01 +00:00
else
2017-09-20 22:57:26 +00:00
{
2017-11-26 01:18:17 +00:00
draw - > AddLine ( wpos + ImVec2 ( std : : max ( - 10.0 , ( fbegin - m_zvStart ) * pxns + 2 ) , fy + round ( ty / 2 ) ) , wpos + ImVec2 ( std : : min ( w + 20.0 , ( fend - m_zvStart ) * pxns - 2 ) , fy + round ( ty / 2 ) ) , color ) ;
2017-09-20 22:57:26 +00:00
}
}
2017-10-22 15:48:01 +00:00
}
2017-09-20 22:57:26 +00:00
2018-02-13 13:57:47 +00:00
const auto fend = m_worker . GetFrameEnd ( zrange . second - 1 ) ;
2017-10-22 15:48:01 +00:00
if ( fend = = m_zvEnd )
{
draw - > AddLine ( wpos + ImVec2 ( ( fend - m_zvStart ) * pxns , 0 ) , wpos + ImVec2 ( ( fend - m_zvStart ) * pxns , wh ) , 0x22FFFFFF ) ;
2017-09-20 22:57:26 +00:00
}
2017-10-13 13:26:18 +00:00
return hover ;
2017-10-12 20:27:17 +00:00
}
void View : : DrawZones ( )
{
2017-10-14 13:47:06 +00:00
m_msgHighlight = nullptr ;
2017-10-12 20:27:17 +00:00
if ( m_zvStart = = m_zvEnd ) return ;
assert ( m_zvStart < m_zvEnd ) ;
ImGuiWindow * window = ImGui : : GetCurrentWindow ( ) ;
if ( window - > SkipItems ) return ;
2017-11-11 22:13:54 +00:00
m_gpuThread = 0 ;
m_gpuStart = 0 ;
m_gpuEnd = 0 ;
2017-10-13 13:26:18 +00:00
const auto linepos = ImGui : : GetCursorScreenPos ( ) ;
const auto lineh = ImGui : : GetContentRegionAvail ( ) . y ;
auto drawMouseLine = DrawZoneFrames ( ) ;
2017-10-12 20:27:17 +00:00
ImGui : : BeginChild ( " ##zoneWin " , ImVec2 ( ImGui : : GetWindowContentRegionWidth ( ) , ImGui : : GetContentRegionAvail ( ) . y ) , false , ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_NoScrollWithMouse ) ;
window = ImGui : : GetCurrentWindow ( ) ;
const auto wpos = ImGui : : GetCursorScreenPos ( ) ;
const auto w = ImGui : : GetWindowContentRegionWidth ( ) - 1 ;
const auto h = std : : max < float > ( m_zvHeight , ImGui : : GetContentRegionAvail ( ) . y - 4 ) ; // magic border value
auto draw = ImGui : : GetWindowDrawList ( ) ;
ImGui : : InvisibleButton ( " ##zones " , ImVec2 ( w , h ) ) ;
bool hover = ImGui : : IsItemHovered ( ) ;
2017-10-28 10:37:34 +00:00
const auto timespan = m_zvEnd - m_zvStart ;
2017-10-12 20:27:17 +00:00
auto pxns = w / double ( timespan ) ;
2017-10-13 13:26:18 +00:00
if ( hover )
{
drawMouseLine = true ;
HandleZoneViewMouse ( timespan , wpos , w , pxns ) ;
}
2017-09-21 00:16:01 +00:00
2017-10-28 10:37:34 +00:00
const auto nspx = 1.0 / pxns ;
2017-10-12 17:47:56 +00:00
const auto ty = ImGui : : GetFontSize ( ) ;
const auto ostep = ty + 1 ;
2017-10-12 20:27:17 +00:00
int offset = 0 ;
2017-10-12 17:47:56 +00:00
const auto to = 9.f ;
const auto th = ( ty - to ) * sqrt ( 3 ) * 0.5 ;
2017-11-11 21:56:05 +00:00
// gpu zones
if ( m_drawGpuZones )
{
2018-02-13 13:57:47 +00:00
for ( size_t i = 0 ; i < m_worker . GetGpuData ( ) . size ( ) ; i + + )
2017-11-11 21:56:05 +00:00
{
2018-02-13 13:57:47 +00:00
const auto & v = m_worker . GetGpuData ( ) [ i ] ;
if ( ! Visible ( v ) ) continue ;
2017-11-11 21:56:05 +00:00
draw - > AddLine ( wpos + ImVec2 ( 0 , offset + ostep - 1 ) , wpos + ImVec2 ( w , offset + ostep - 1 ) , 0x33FFFFFF ) ;
2018-02-13 13:57:47 +00:00
bool & showFull = ShowFull ( v ) ;
if ( showFull )
2017-11-11 21:56:05 +00:00
{
2017-11-12 00:05:55 +00:00
draw - > AddTriangleFilled ( wpos + ImVec2 ( to / 2 , offset + to / 2 ) , wpos + ImVec2 ( ty - to / 2 , offset + to / 2 ) , wpos + ImVec2 ( ty * 0.5 , offset + to / 2 + th ) , 0xFFFFAAAA ) ;
2017-11-11 21:56:05 +00:00
}
else
{
2017-11-12 00:05:55 +00:00
draw - > AddTriangle ( wpos + ImVec2 ( to / 2 , offset + to / 2 ) , wpos + ImVec2 ( to / 2 , offset + ty - to / 2 ) , wpos + ImVec2 ( to / 2 + th , offset + ty * 0.5 ) , 0xFF886666 ) ;
2017-11-11 21:56:05 +00:00
}
char buf [ 64 ] ;
2018-03-13 15:23:10 +00:00
sprintf ( buf , " GPU context %zu " , i ) ;
2018-02-13 13:57:47 +00:00
draw - > AddText ( wpos + ImVec2 ( ty , offset ) , showFull ? 0xFFFFAAAA : 0xFF886666 , buf ) ;
2017-11-11 21:56:05 +00:00
2017-11-17 23:33:53 +00:00
if ( hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( 0 , offset ) , wpos + ImVec2 ( ty + ImGui : : CalcTextSize ( buf ) . x , offset + ty ) ) )
2017-11-11 21:56:05 +00:00
{
2017-11-17 23:33:53 +00:00
if ( ImGui : : IsMouseClicked ( 0 ) )
{
2018-02-13 13:57:47 +00:00
showFull = ! showFull ;
2017-11-17 23:33:53 +00:00
}
ImGui : : BeginTooltip ( ) ;
ImGui : : Text ( " %s " , buf ) ;
ImGui : : Separator ( ) ;
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " Thread: %s " , m_worker . GetThreadString ( v - > thread ) ) ;
2017-11-17 23:56:05 +00:00
if ( ! v - > timeline . empty ( ) )
{
const auto t = v - > timeline . front ( ) - > gpuStart ;
if ( t ! = std : : numeric_limits < int64_t > : : max ( ) )
{
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " Appeared at %s " , TimeToString ( t - m_worker . GetFrameTime ( 0 ) ) ) ;
2017-11-17 23:56:05 +00:00
}
}
2017-11-18 00:14:37 +00:00
ImGui : : Text ( " Zone count: %s " , RealToString ( v - > count , true ) ) ;
ImGui : : Text ( " Top-level zones: %s " , RealToString ( v - > timeline . size ( ) , true ) ) ;
2017-11-17 23:33:53 +00:00
ImGui : : Text ( " Query accuracy bits: %i " , v - > accuracyBits ) ;
ImGui : : EndTooltip ( ) ;
2017-11-11 21:56:05 +00:00
}
offset + = ostep ;
2018-02-13 13:57:47 +00:00
if ( showFull )
2017-11-11 21:56:05 +00:00
{
2017-11-13 23:48:26 +00:00
const auto depth = DrawGpuZoneLevel ( v - > timeline , hover , pxns , wpos , offset , 0 , v - > thread ) ;
2017-11-11 21:56:05 +00:00
offset + = ostep * depth ;
}
offset + = ostep * 0.2f ;
}
}
// zones
LockHighlight nextLockHighlight { - 1 } ;
2018-02-13 13:57:47 +00:00
for ( const auto & v : m_worker . GetThreadData ( ) )
2017-09-21 00:16:01 +00:00
{
2018-02-13 13:57:47 +00:00
if ( ! Visible ( v ) ) continue ;
2017-10-22 11:13:26 +00:00
2017-09-22 23:29:27 +00:00
draw - > AddLine ( wpos + ImVec2 ( 0 , offset + ostep - 1 ) , wpos + ImVec2 ( w , offset + ostep - 1 ) , 0x33FFFFFF ) ;
2017-10-12 17:47:56 +00:00
2018-02-13 13:57:47 +00:00
bool & showFull = ShowFull ( v ) ;
if ( showFull )
2017-10-12 17:47:56 +00:00
{
draw - > AddTriangleFilled ( wpos + ImVec2 ( to / 2 , offset + to / 2 ) , wpos + ImVec2 ( ty - to / 2 , offset + to / 2 ) , wpos + ImVec2 ( ty * 0.5 , offset + to / 2 + th ) , 0xFFFFFFFF ) ;
2017-10-14 13:03:28 +00:00
auto it = std : : lower_bound ( v - > messages . begin ( ) , v - > messages . end ( ) , m_zvStart , [ ] ( const auto & lhs , const auto & rhs ) { return lhs - > time < rhs ; } ) ;
2017-11-21 01:28:46 +00:00
auto end = std : : lower_bound ( it , v - > messages . end ( ) , m_zvEnd , [ ] ( const auto & lhs , const auto & rhs ) { return lhs - > time < rhs ; } ) ;
2017-10-14 13:03:28 +00:00
while ( it < end )
{
2017-10-28 10:37:34 +00:00
const auto next = std : : upper_bound ( it , v - > messages . end ( ) , ( * it ) - > time + MinVisSize * nspx , [ ] ( const auto & lhs , const auto & rhs ) { return lhs < rhs - > time ; } ) ;
const auto dist = std : : distance ( it , next ) ;
2017-10-14 13:03:28 +00:00
const auto px = ( ( * it ) - > time - m_zvStart ) * pxns ;
2017-10-28 10:37:34 +00:00
if ( dist > 1 )
{
draw - > AddTriangleFilled ( wpos + ImVec2 ( px - ( ty - to ) * 0.5 , offset + to ) , wpos + ImVec2 ( px + ( ty - to ) * 0.5 , offset + to ) , wpos + ImVec2 ( px , offset + to + th ) , 0xFFDDDDDD ) ;
}
2017-10-14 13:03:28 +00:00
draw - > AddTriangle ( wpos + ImVec2 ( px - ( ty - to ) * 0.5 , offset + to ) , wpos + ImVec2 ( px + ( ty - to ) * 0.5 , offset + to ) , wpos + ImVec2 ( px , offset + to + th ) , 0xFFDDDDDD ) ;
if ( hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( px - ( ty - to ) * 0.5 - 1 , offset ) , wpos + ImVec2 ( px + ( ty - to ) * 0.5 + 1 , offset + ty ) ) )
{
ImGui : : BeginTooltip ( ) ;
2017-10-28 10:37:34 +00:00
if ( dist > 1 )
{
ImGui : : Text ( " %i messages " , ( int ) dist ) ;
}
else
{
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " %s " , TimeToString ( ( * it ) - > time - m_worker . GetFrameBegin ( 0 ) ) ) ;
2017-11-17 23:51:04 +00:00
ImGui : : Separator ( ) ;
ImGui : : Text ( " Message text: " ) ;
2018-02-13 13:57:47 +00:00
ImGui : : TextColored ( ImVec4 ( 0xCC / 255.f , 0xCC / 255.f , 0x22 / 255.f , 1.f ) , " %s " , m_worker . GetString ( ( * it ) - > ref ) ) ;
2017-10-28 10:37:34 +00:00
}
2017-10-14 13:03:28 +00:00
ImGui : : EndTooltip ( ) ;
2017-10-14 13:47:06 +00:00
m_msgHighlight = * it ;
2017-10-14 13:03:28 +00:00
}
2017-10-28 10:37:34 +00:00
it = next ;
2017-10-14 13:03:28 +00:00
}
2017-10-12 17:47:56 +00:00
}
else
{
draw - > AddTriangle ( wpos + ImVec2 ( to / 2 , offset + to / 2 ) , wpos + ImVec2 ( to / 2 , offset + ty - to / 2 ) , wpos + ImVec2 ( to / 2 + th , offset + ty * 0.5 ) , 0xFF888888 ) ;
}
2018-02-13 13:57:47 +00:00
const auto txt = m_worker . GetThreadString ( v - > id ) ;
2017-11-11 22:13:54 +00:00
const auto txtsz = ImGui : : CalcTextSize ( txt ) ;
if ( m_gpuThread = = v - > id )
{
draw - > AddRectFilled ( wpos + ImVec2 ( 0 , offset ) , wpos + ImVec2 ( ty + txtsz . x + 4 , offset + ty ) , 0x448888DD ) ;
draw - > AddRect ( wpos + ImVec2 ( 0 , offset ) , wpos + ImVec2 ( ty + txtsz . x + 4 , offset + ty ) , 0x888888DD ) ;
}
2017-11-13 23:48:26 +00:00
if ( m_gpuInfoWindow & & m_gpuInfoWindowThread = = v - > id )
2017-11-12 00:32:21 +00:00
{
draw - > AddRectFilled ( wpos + ImVec2 ( 0 , offset ) , wpos + ImVec2 ( ty + txtsz . x + 4 , offset + ty ) , 0x4488DD88 ) ;
draw - > AddRect ( wpos + ImVec2 ( 0 , offset ) , wpos + ImVec2 ( ty + txtsz . x + 4 , offset + ty ) , 0x8888DD88 ) ;
}
2018-02-13 13:57:47 +00:00
draw - > AddText ( wpos + ImVec2 ( ty , offset ) , showFull ? 0xFFFFFFFF : 0xFF888888 , txt ) ;
2017-10-12 17:47:56 +00:00
2017-11-18 00:03:40 +00:00
if ( hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( 0 , offset ) , wpos + ImVec2 ( ty + txtsz . x , offset + ty ) ) )
2017-10-12 17:47:56 +00:00
{
2017-11-18 00:03:40 +00:00
if ( ImGui : : IsMouseClicked ( 0 ) )
{
2018-02-13 13:57:47 +00:00
showFull = ! showFull ;
2017-11-18 00:03:40 +00:00
}
ImGui : : BeginTooltip ( ) ;
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " %s " , m_worker . GetThreadString ( v - > id ) ) ;
2017-11-18 00:03:40 +00:00
if ( ! v - > timeline . empty ( ) )
{
2017-11-18 00:14:55 +00:00
ImGui : : Separator ( ) ;
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " Appeared at %s " , TimeToString ( v - > timeline . front ( ) - > start - m_worker . GetFrameBegin ( 0 ) ) ) ;
2017-11-18 00:14:55 +00:00
ImGui : : Text ( " Zone count: %s " , RealToString ( v - > count , true ) ) ;
ImGui : : Text ( " Top-level zones: %s " , RealToString ( v - > timeline . size ( ) , true ) ) ;
2017-11-18 00:03:40 +00:00
}
ImGui : : EndTooltip ( ) ;
2017-10-12 17:47:56 +00:00
}
2017-09-22 23:29:27 +00:00
offset + = ostep ;
2018-02-13 13:57:47 +00:00
if ( showFull )
2017-10-12 17:47:56 +00:00
{
m_lastCpu = - 1 ;
2017-10-13 11:32:23 +00:00
if ( m_drawZones )
{
const auto depth = DrawZoneLevel ( v - > timeline , hover , pxns , wpos , offset , 0 ) ;
offset + = ostep * depth ;
}
2017-09-23 22:07:06 +00:00
2017-10-13 11:32:23 +00:00
if ( m_drawLocks )
{
const auto depth = DrawLocks ( v - > id , hover , pxns , wpos , offset , nextLockHighlight ) ;
offset + = ostep * depth ;
}
2017-10-12 17:47:56 +00:00
}
offset + = ostep * 0.2f ;
2017-09-23 22:07:06 +00:00
}
2017-10-06 00:19:25 +00:00
m_lockHighlight = nextLockHighlight ;
2017-10-12 20:27:17 +00:00
2017-10-13 12:54:32 +00:00
if ( m_drawPlots )
{
2017-10-13 13:15:57 +00:00
offset = DrawPlots ( offset , pxns , wpos , hover ) ;
2017-10-13 12:54:32 +00:00
}
2017-10-12 20:27:17 +00:00
const auto scrollPos = ImGui : : GetScrollY ( ) ;
if ( scrollPos = = 0 & & m_zvScroll ! = 0 )
{
m_zvHeight = 0 ;
}
else
{
if ( offset > m_zvHeight ) m_zvHeight = offset ;
}
m_zvScroll = scrollPos ;
ImGui : : EndChild ( ) ;
2017-10-13 13:26:18 +00:00
2017-11-18 12:40:49 +00:00
if ( m_gpuStart ! = 0 & & m_gpuEnd ! = 0 )
2017-11-11 22:13:54 +00:00
{
const auto px0 = ( m_gpuStart - m_zvStart ) * pxns ;
2017-11-18 12:40:49 +00:00
const auto px1 = std : : max ( px0 + std : : max ( 1.0 , pxns * 0.5 ) , ( m_gpuEnd - m_zvStart ) * pxns ) ;
2017-11-11 22:13:54 +00:00
draw - > AddRectFilled ( ImVec2 ( wpos . x + px0 , linepos . y ) , ImVec2 ( wpos . x + px1 , linepos . y + lineh ) , 0x228888DD ) ;
draw - > AddRect ( ImVec2 ( wpos . x + px0 , linepos . y ) , ImVec2 ( wpos . x + px1 , linepos . y + lineh ) , 0x448888DD ) ;
}
2017-11-12 00:32:21 +00:00
if ( m_gpuInfoWindow )
{
const auto px0 = ( m_gpuInfoWindow - > cpuStart - m_zvStart ) * pxns ;
2017-11-18 12:40:49 +00:00
const auto px1 = std : : max ( px0 + std : : max ( 1.0 , pxns * 0.5 ) , ( m_gpuInfoWindow - > cpuEnd - m_zvStart ) * pxns ) ;
2017-11-12 00:32:21 +00:00
draw - > AddRectFilled ( ImVec2 ( wpos . x + px0 , linepos . y ) , ImVec2 ( wpos . x + px1 , linepos . y + lineh ) , 0x2288DD88 ) ;
draw - > AddRect ( ImVec2 ( wpos . x + px0 , linepos . y ) , ImVec2 ( wpos . x + px1 , linepos . y + lineh ) , 0x4488DD88 ) ;
}
2017-11-11 22:13:54 +00:00
2018-03-04 21:21:35 +00:00
if ( m_highlight . active & & m_highlight . start ! = m_highlight . end )
2017-10-15 14:42:56 +00:00
{
2018-03-04 21:21:35 +00:00
const auto s = std : : min ( m_highlight . start , m_highlight . end ) ;
const auto e = std : : max ( m_highlight . start , m_highlight . end ) ;
2017-10-15 14:42:56 +00:00
draw - > AddRectFilled ( ImVec2 ( wpos . x + ( s - m_zvStart ) * pxns , linepos . y ) , ImVec2 ( wpos . x + ( e - m_zvStart ) * pxns , linepos . y + lineh ) , 0x22DD8888 ) ;
draw - > AddRect ( ImVec2 ( wpos . x + ( s - m_zvStart ) * pxns , linepos . y ) , ImVec2 ( wpos . x + ( e - m_zvStart ) * pxns , linepos . y + lineh ) , 0x44DD8888 ) ;
ImGui : : BeginTooltip ( ) ;
ImGui : : Text ( " %s " , TimeToString ( e - s ) ) ;
ImGui : : EndTooltip ( ) ;
}
else if ( drawMouseLine )
2017-10-13 13:26:18 +00:00
{
auto & io = ImGui : : GetIO ( ) ;
draw - > AddLine ( ImVec2 ( io . MousePos . x , linepos . y ) , ImVec2 ( io . MousePos . x , linepos . y + lineh ) , 0x33FFFFFF ) ;
}
2017-09-23 22:07:06 +00:00
}
2017-10-22 13:37:24 +00:00
int View : : DrawZoneLevel ( const Vector < ZoneEvent * > & vec , bool hover , double pxns , const ImVec2 & wpos , int _offset , int depth )
2017-09-23 22:07:06 +00:00
{
2018-02-13 13:57:47 +00:00
const auto delay = m_worker . GetDelay ( ) ;
const auto resolution = m_worker . GetResolution ( ) ;
2017-10-28 20:20:39 +00:00
// cast to uint64_t, so that unended zones (end = -1) are still drawn
2018-02-13 13:57:47 +00:00
auto it = std : : lower_bound ( vec . begin ( ) , vec . end ( ) , m_zvStart - delay , [ ] ( const auto & l , const auto & r ) { return ( uint64_t ) l - > end < ( uint64_t ) r ; } ) ;
2017-10-12 17:14:03 +00:00
if ( it = = vec . end ( ) ) return depth ;
2018-02-13 13:57:47 +00:00
const auto zitend = std : : lower_bound ( it , vec . end ( ) , m_zvEnd + resolution , [ ] ( const auto & l , const auto & r ) { return l - > start < r ; } ) ;
2017-10-12 17:14:03 +00:00
if ( it = = zitend ) return depth ;
2017-10-12 20:27:17 +00:00
const auto w = ImGui : : GetWindowContentRegionWidth ( ) - 1 ;
2017-10-12 17:14:03 +00:00
const auto ty = ImGui : : GetFontSize ( ) ;
const auto ostep = ty + 1 ;
const auto offset = _offset + ostep * depth ;
auto draw = ImGui : : GetWindowDrawList ( ) ;
2018-02-13 13:57:47 +00:00
const auto dsz = delay * pxns ;
const auto rsz = resolution * pxns ;
2017-10-12 17:14:03 +00:00
depth + + ;
int maxdepth = depth ;
while ( it < zitend )
2017-09-23 22:07:06 +00:00
{
2017-10-12 17:14:03 +00:00
auto & ev = * * it ;
2018-02-13 13:57:47 +00:00
auto & srcloc = m_worker . GetSourceLocation ( ev . srcloc ) ;
2017-11-11 21:56:05 +00:00
const auto color = GetZoneColor ( ev ) ;
2018-02-13 13:57:47 +00:00
const auto end = m_worker . GetZoneEnd ( ev ) ;
2017-11-18 12:40:49 +00:00
const auto zsz = std : : max ( ( end - ev . start ) * pxns , pxns * 0.5 ) ;
2017-10-12 17:14:03 +00:00
if ( zsz < MinVisSize )
2017-09-21 00:16:01 +00:00
{
2017-10-12 17:14:03 +00:00
int num = 1 ;
const auto px0 = ( ev . start - m_zvStart ) * pxns ;
auto px1 = ( end - m_zvStart ) * pxns ;
auto rend = end ;
for ( ; ; )
2017-09-21 20:12:19 +00:00
{
2017-10-12 17:14:03 +00:00
+ + it ;
if ( it = = zitend ) break ;
2018-02-13 13:57:47 +00:00
const auto nend = m_worker . GetZoneEnd ( * * it ) ;
2017-10-12 17:14:03 +00:00
const auto pxnext = ( nend - m_zvStart ) * pxns ;
if ( pxnext - px1 > = MinVisSize * 2 ) break ;
px1 = pxnext ;
rend = nend ;
num + + ;
}
2017-11-07 20:48:24 +00:00
draw - > AddRectFilled ( wpos + ImVec2 ( std : : max ( px0 , - 10.0 ) , offset ) , wpos + ImVec2 ( std : : min ( std : : max ( px1 , px0 + MinVisSize ) , double ( w + 10 ) ) , offset + ty ) , color ) ;
2017-10-28 14:14:52 +00:00
if ( hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( std : : max ( px0 , - 10.0 ) , offset ) , wpos + ImVec2 ( std : : min ( std : : max ( px1 , px0 + MinVisSize ) , double ( w + 10 ) ) , offset + ty ) ) )
2017-10-12 17:14:03 +00:00
{
2017-11-07 20:51:21 +00:00
if ( num > 1 )
{
ImGui : : BeginTooltip ( ) ;
2017-11-25 14:48:41 +00:00
ImGui : : Text ( " Zones too small to display: %s " , RealToString ( num , true ) ) ;
2017-11-17 23:51:04 +00:00
ImGui : : Separator ( ) ;
2017-11-07 20:51:21 +00:00
ImGui : : Text ( " Execution time: %s " , TimeToString ( rend - ev . start ) ) ;
ImGui : : EndTooltip ( ) ;
2017-09-26 20:08:58 +00:00
2017-11-07 20:51:21 +00:00
if ( ImGui : : IsMouseClicked ( 2 ) & & rend - ev . start > 0 )
{
2017-11-27 21:12:26 +00:00
ZoomToRange ( ev . start , rend ) ;
2017-11-07 20:51:21 +00:00
}
}
else
2017-09-29 17:13:53 +00:00
{
2017-11-07 20:51:21 +00:00
ZoneTooltip ( ev ) ;
if ( ImGui : : IsMouseClicked ( 2 ) & & rend - ev . start > 0 )
{
ZoomToZone ( ev ) ;
}
if ( ImGui : : IsMouseClicked ( 0 ) )
{
m_zoneInfoWindow = & ev ;
2017-11-12 00:25:44 +00:00
m_gpuInfoWindow = nullptr ;
2017-11-07 20:51:21 +00:00
}
2017-09-29 17:13:53 +00:00
}
2017-09-23 22:07:06 +00:00
}
2017-10-12 17:14:03 +00:00
char tmp [ 32 ] ;
sprintf ( tmp , " %i " , num ) ;
const auto tsz = ImGui : : CalcTextSize ( tmp ) ;
if ( tsz . x < px1 - px0 )
{
const auto x = px0 + ( px1 - px0 - tsz . x ) / 2 ;
2017-11-25 14:45:16 +00:00
DrawTextContrast ( draw , wpos + ImVec2 ( x , offset ) , 0xFF4488DD , tmp ) ;
2017-10-12 17:14:03 +00:00
}
}
else
{
const char * zoneName ;
2017-11-14 22:31:24 +00:00
if ( srcloc . name . active )
2017-10-12 17:14:03 +00:00
{
2018-02-13 13:57:47 +00:00
zoneName = m_worker . GetString ( srcloc . name ) ;
2017-10-12 17:14:03 +00:00
}
2017-09-23 22:07:06 +00:00
else
{
2018-02-13 13:57:47 +00:00
zoneName = m_worker . GetString ( srcloc . function ) ;
2017-10-12 17:14:03 +00:00
}
2017-09-28 17:31:27 +00:00
2017-11-14 22:31:24 +00:00
int dmul = ev . text . active ? 2 : 1 ;
2017-09-29 16:40:55 +00:00
2017-10-12 17:14:03 +00:00
bool migration = false ;
if ( m_lastCpu ! = ev . cpu_start )
{
if ( m_lastCpu ! = - 1 )
2017-10-01 17:58:53 +00:00
{
2017-10-12 17:14:03 +00:00
migration = true ;
2017-10-01 17:58:53 +00:00
}
2017-10-12 17:14:03 +00:00
m_lastCpu = ev . cpu_start ;
}
2017-10-01 17:58:53 +00:00
2017-10-12 17:14:03 +00:00
if ( ! ev . child . empty ( ) )
{
const auto d = DrawZoneLevel ( ev . child , hover , pxns , wpos , _offset , depth ) ;
if ( d > maxdepth ) maxdepth = d ;
}
2017-10-01 17:58:53 +00:00
2018-03-24 01:00:20 +00:00
if ( ev . end > = 0 & & m_lastCpu ! = ev . cpu_end )
2017-10-12 17:14:03 +00:00
{
m_lastCpu = ev . cpu_end ;
migration = true ;
}
2017-10-01 17:58:53 +00:00
2017-10-22 11:56:05 +00:00
auto tsz = ImGui : : CalcTextSize ( zoneName ) ;
if ( tsz . x > zsz )
{
zoneName = ShortenNamespace ( zoneName ) ;
tsz = ImGui : : CalcTextSize ( zoneName ) ;
}
2017-10-12 17:14:03 +00:00
const auto pr0 = ( ev . start - m_zvStart ) * pxns ;
const auto pr1 = ( end - m_zvStart ) * pxns ;
const auto px0 = std : : max ( pr0 , - 10.0 ) ;
2017-11-18 12:40:49 +00:00
const auto px1 = std : : max ( { std : : min ( pr1 , double ( w + 10 ) ) , px0 + pxns * 0.5 , px0 + MinVisSize } ) ;
draw - > AddRectFilled ( wpos + ImVec2 ( px0 , offset ) , wpos + ImVec2 ( px1 , offset + tsz . y ) , color ) ;
draw - > AddRect ( wpos + ImVec2 ( px0 , offset ) , wpos + ImVec2 ( px1 , offset + tsz . y ) , GetZoneHighlight ( ev , migration ) , 0.f , - 1 , GetZoneThickness ( ev ) ) ;
2017-10-12 17:14:03 +00:00
if ( dsz * dmul > = MinVisSize )
{
2017-11-07 20:48:24 +00:00
draw - > AddRectFilled ( wpos + ImVec2 ( pr0 , offset ) , wpos + ImVec2 ( std : : min ( pr0 + dsz * dmul , pr1 ) , offset + tsz . y ) , 0x882222DD ) ;
draw - > AddRectFilled ( wpos + ImVec2 ( pr1 , offset ) , wpos + ImVec2 ( pr1 + dsz , offset + tsz . y ) , 0x882222DD ) ;
2017-10-12 17:14:03 +00:00
}
if ( rsz > = MinVisSize )
{
2017-11-07 21:02:27 +00:00
draw - > AddLine ( wpos + ImVec2 ( pr0 + rsz , offset + round ( tsz . y / 2 ) ) , wpos + ImVec2 ( pr0 - rsz , offset + round ( tsz . y / 2 ) ) , 0xAAFFFFFF ) ;
draw - > AddLine ( wpos + ImVec2 ( pr0 + rsz , offset + round ( tsz . y / 4 ) ) , wpos + ImVec2 ( pr0 + rsz , offset + round ( 3 * tsz . y / 4 ) ) , 0xAAFFFFFF ) ;
draw - > AddLine ( wpos + ImVec2 ( pr0 - rsz , offset + round ( tsz . y / 4 ) ) , wpos + ImVec2 ( pr0 - rsz , offset + round ( 3 * tsz . y / 4 ) ) , 0xAAFFFFFF ) ;
2017-09-29 16:55:21 +00:00
2017-11-07 21:02:27 +00:00
draw - > AddLine ( wpos + ImVec2 ( pr1 + rsz , offset + round ( tsz . y / 2 ) ) , wpos + ImVec2 ( pr1 - rsz , offset + round ( tsz . y / 2 ) ) , 0xAAFFFFFF ) ;
draw - > AddLine ( wpos + ImVec2 ( pr1 + rsz , offset + round ( tsz . y / 4 ) ) , wpos + ImVec2 ( pr1 + rsz , offset + round ( 3 * tsz . y / 4 ) ) , 0xAAFFFFFF ) ;
draw - > AddLine ( wpos + ImVec2 ( pr1 - rsz , offset + round ( tsz . y / 4 ) ) , wpos + ImVec2 ( pr1 - rsz , offset + round ( 3 * tsz . y / 4 ) ) , 0xAAFFFFFF ) ;
2017-10-12 17:14:03 +00:00
}
if ( tsz . x < zsz )
{
const auto x = ( ev . start - m_zvStart ) * pxns + ( ( end - ev . start ) * pxns - tsz . x ) / 2 ;
if ( x < 0 | | x > w - tsz . x )
2017-09-24 14:25:07 +00:00
{
2017-11-18 12:40:49 +00:00
ImGui : : PushClipRect ( wpos + ImVec2 ( px0 , offset ) , wpos + ImVec2 ( px1 , offset + tsz . y * 2 ) , true ) ;
2017-11-25 14:45:16 +00:00
DrawTextContrast ( draw , wpos + ImVec2 ( std : : max ( std : : max ( 0. , px0 ) , std : : min ( double ( w - tsz . x ) , x ) ) , offset ) , 0xFFFFFFFF , zoneName ) ;
2017-10-12 17:14:03 +00:00
ImGui : : PopClipRect ( ) ;
2017-09-24 14:25:07 +00:00
}
2017-11-18 12:40:49 +00:00
else if ( ev . start = = ev . end )
{
2017-11-25 14:45:16 +00:00
DrawTextContrast ( draw , wpos + ImVec2 ( px0 + ( px1 - px0 - tsz . x ) * 0.5 , offset ) , 0xFFFFFFFF , zoneName ) ;
2017-11-18 12:40:49 +00:00
}
2017-09-24 14:25:07 +00:00
else
{
2017-11-25 14:45:16 +00:00
DrawTextContrast ( draw , wpos + ImVec2 ( x , offset ) , 0xFFFFFFFF , zoneName ) ;
2017-09-24 14:25:07 +00:00
}
2017-10-12 17:14:03 +00:00
}
else
{
2017-11-18 12:40:49 +00:00
ImGui : : PushClipRect ( wpos + ImVec2 ( px0 , offset ) , wpos + ImVec2 ( px1 , offset + tsz . y * 2 ) , true ) ;
2017-11-25 14:45:16 +00:00
DrawTextContrast ( draw , wpos + ImVec2 ( ( ev . start - m_zvStart ) * pxns , offset ) , 0xFFFFFFFF , zoneName ) ;
2017-10-12 17:14:03 +00:00
ImGui : : PopClipRect ( ) ;
}
2017-09-21 00:16:01 +00:00
2017-11-18 12:40:49 +00:00
if ( hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( px0 , offset ) , wpos + ImVec2 ( px1 , offset + tsz . y ) ) )
2017-10-12 17:14:03 +00:00
{
ZoneTooltip ( ev ) ;
2017-09-26 19:49:50 +00:00
2017-11-27 21:41:30 +00:00
if ( ! m_zoomAnim . active & & ImGui : : IsMouseClicked ( 2 ) )
2017-10-12 17:14:03 +00:00
{
ZoomToZone ( ev ) ;
}
if ( ImGui : : IsMouseClicked ( 0 ) )
{
m_zoneInfoWindow = & ev ;
2017-11-12 00:25:44 +00:00
m_gpuInfoWindow = nullptr ;
2017-09-24 14:25:07 +00:00
}
}
2017-10-12 17:14:03 +00:00
+ + it ;
2017-09-23 22:07:06 +00:00
}
2017-09-21 00:16:01 +00:00
}
2017-09-23 22:12:26 +00:00
return maxdepth ;
2017-09-20 22:57:26 +00:00
}
2017-11-13 23:48:26 +00:00
int View : : DrawGpuZoneLevel ( const Vector < GpuEvent * > & vec , bool hover , double pxns , const ImVec2 & wpos , int _offset , int depth , uint64_t thread )
2017-11-11 21:56:05 +00:00
{
2018-02-13 13:57:47 +00:00
const auto delay = m_worker . GetDelay ( ) ;
const auto resolution = m_worker . GetResolution ( ) ;
2017-11-11 21:56:05 +00:00
// cast to uint64_t, so that unended zones (end = -1) are still drawn
2018-02-13 13:57:47 +00:00
auto it = std : : lower_bound ( vec . begin ( ) , vec . end ( ) , m_zvStart - delay , [ ] ( const auto & l , const auto & r ) { return ( uint64_t ) l - > gpuEnd < ( uint64_t ) r ; } ) ;
2017-11-11 21:56:05 +00:00
if ( it = = vec . end ( ) ) return depth ;
2018-02-13 13:57:47 +00:00
const auto zitend = std : : lower_bound ( it , vec . end ( ) , m_zvEnd + resolution , [ ] ( const auto & l , const auto & r ) { return l - > gpuStart < r ; } ) ;
2017-11-11 21:56:05 +00:00
if ( it = = zitend ) return depth ;
const auto w = ImGui : : GetWindowContentRegionWidth ( ) - 1 ;
const auto ty = ImGui : : GetFontSize ( ) ;
const auto ostep = ty + 1 ;
const auto offset = _offset + ostep * depth ;
auto draw = ImGui : : GetWindowDrawList ( ) ;
2018-02-13 13:57:47 +00:00
const auto dsz = delay * pxns ;
const auto rsz = resolution * pxns ;
2017-11-11 21:56:05 +00:00
depth + + ;
int maxdepth = depth ;
while ( it < zitend )
{
auto & ev = * * it ;
2018-02-13 13:57:47 +00:00
auto & srcloc = m_worker . GetSourceLocation ( ev . srcloc ) ;
2017-11-11 21:56:05 +00:00
const auto color = GetZoneColor ( ev ) ;
2018-02-13 13:57:47 +00:00
const auto end = m_worker . GetZoneEnd ( ev ) ;
2017-11-14 23:08:21 +00:00
if ( end = = std : : numeric_limits < int64_t > : : max ( ) ) break ;
2017-11-18 12:40:49 +00:00
const auto zsz = std : : max ( ( end - ev . gpuStart ) * pxns , pxns * 0.5 ) ;
2017-11-11 21:56:05 +00:00
if ( zsz < MinVisSize )
{
int num = 1 ;
const auto px0 = ( ev . gpuStart - m_zvStart ) * pxns ;
auto px1 = ( end - m_zvStart ) * pxns ;
auto rend = end ;
for ( ; ; )
{
+ + it ;
if ( it = = zitend ) break ;
2018-02-13 13:57:47 +00:00
const auto nend = m_worker . GetZoneEnd ( * * it ) ;
2017-11-11 21:56:05 +00:00
const auto pxnext = ( nend - m_zvStart ) * pxns ;
if ( pxnext - px1 > = MinVisSize * 2 ) break ;
px1 = pxnext ;
rend = nend ;
num + + ;
}
draw - > AddRectFilled ( wpos + ImVec2 ( std : : max ( px0 , - 10.0 ) , offset ) , wpos + ImVec2 ( std : : min ( std : : max ( px1 , px0 + MinVisSize ) , double ( w + 10 ) ) , offset + ty ) , color ) ;
if ( hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( std : : max ( px0 , - 10.0 ) , offset ) , wpos + ImVec2 ( std : : min ( std : : max ( px1 , px0 + MinVisSize ) , double ( w + 10 ) ) , offset + ty ) ) )
{
if ( num > 1 )
{
ImGui : : BeginTooltip ( ) ;
2017-11-25 14:48:41 +00:00
ImGui : : Text ( " Zones too small to display: %s " , RealToString ( num , true ) ) ;
2017-11-17 23:51:04 +00:00
ImGui : : Separator ( ) ;
2017-11-11 21:56:05 +00:00
ImGui : : Text ( " Execution time: %s " , TimeToString ( rend - ev . gpuStart ) ) ;
ImGui : : EndTooltip ( ) ;
if ( ImGui : : IsMouseClicked ( 2 ) & & rend - ev . gpuStart > 0 )
{
2017-11-27 21:12:26 +00:00
ZoomToRange ( ev . gpuStart , rend ) ;
2017-11-11 21:56:05 +00:00
}
}
else
{
ZoneTooltip ( ev ) ;
if ( ImGui : : IsMouseClicked ( 2 ) & & rend - ev . gpuStart > 0 )
{
ZoomToZone ( ev ) ;
}
2017-11-12 00:25:44 +00:00
if ( ImGui : : IsMouseClicked ( 0 ) )
{
m_zoneInfoWindow = nullptr ;
m_gpuInfoWindow = & ev ;
2017-11-13 23:48:26 +00:00
m_gpuInfoWindowThread = thread ;
2017-11-12 00:25:44 +00:00
}
2017-11-11 22:13:54 +00:00
2017-11-13 23:48:26 +00:00
m_gpuThread = thread ;
2017-11-11 22:13:54 +00:00
m_gpuStart = ev . cpuStart ;
m_gpuEnd = ev . cpuEnd ;
2017-11-11 21:56:05 +00:00
}
}
char tmp [ 32 ] ;
sprintf ( tmp , " %i " , num ) ;
const auto tsz = ImGui : : CalcTextSize ( tmp ) ;
if ( tsz . x < px1 - px0 )
{
const auto x = px0 + ( px1 - px0 - tsz . x ) / 2 ;
2017-11-25 14:45:16 +00:00
DrawTextContrast ( draw , wpos + ImVec2 ( x , offset ) , 0xFF4488DD , tmp ) ;
2017-11-11 21:56:05 +00:00
}
}
else
{
if ( ! ev . child . empty ( ) )
{
2017-11-13 23:48:26 +00:00
const auto d = DrawGpuZoneLevel ( ev . child , hover , pxns , wpos , _offset , depth , thread ) ;
2017-11-11 21:56:05 +00:00
if ( d > maxdepth ) maxdepth = d ;
}
2018-02-13 13:57:47 +00:00
const char * zoneName = m_worker . GetString ( srcloc . name ) ;
2017-11-11 21:56:05 +00:00
auto tsz = ImGui : : CalcTextSize ( zoneName ) ;
const auto pr0 = ( ev . gpuStart - m_zvStart ) * pxns ;
const auto pr1 = ( end - m_zvStart ) * pxns ;
const auto px0 = std : : max ( pr0 , - 10.0 ) ;
2017-11-18 12:40:49 +00:00
const auto px1 = std : : max ( { std : : min ( pr1 , double ( w + 10 ) ) , px0 + pxns * 0.5 , px0 + MinVisSize } ) ;
draw - > AddRectFilled ( wpos + ImVec2 ( px0 , offset ) , wpos + ImVec2 ( px1 , offset + tsz . y ) , color ) ;
draw - > AddRect ( wpos + ImVec2 ( px0 , offset ) , wpos + ImVec2 ( px1 , offset + tsz . y ) , GetZoneHighlight ( ev ) , 0.f , - 1 , GetZoneThickness ( ev ) ) ;
2017-11-11 21:56:05 +00:00
if ( dsz > = MinVisSize )
{
draw - > AddRectFilled ( wpos + ImVec2 ( pr0 , offset ) , wpos + ImVec2 ( std : : min ( pr0 + dsz , pr1 ) , offset + tsz . y ) , 0x882222DD ) ;
draw - > AddRectFilled ( wpos + ImVec2 ( pr1 , offset ) , wpos + ImVec2 ( pr1 + dsz , offset + tsz . y ) , 0x882222DD ) ;
}
if ( rsz > = MinVisSize )
{
draw - > AddLine ( wpos + ImVec2 ( pr0 + rsz , offset + round ( tsz . y / 2 ) ) , wpos + ImVec2 ( pr0 - rsz , offset + round ( tsz . y / 2 ) ) , 0xAAFFFFFF ) ;
draw - > AddLine ( wpos + ImVec2 ( pr0 + rsz , offset + round ( tsz . y / 4 ) ) , wpos + ImVec2 ( pr0 + rsz , offset + round ( 3 * tsz . y / 4 ) ) , 0xAAFFFFFF ) ;
draw - > AddLine ( wpos + ImVec2 ( pr0 - rsz , offset + round ( tsz . y / 4 ) ) , wpos + ImVec2 ( pr0 - rsz , offset + round ( 3 * tsz . y / 4 ) ) , 0xAAFFFFFF ) ;
draw - > AddLine ( wpos + ImVec2 ( pr1 + rsz , offset + round ( tsz . y / 2 ) ) , wpos + ImVec2 ( pr1 - rsz , offset + round ( tsz . y / 2 ) ) , 0xAAFFFFFF ) ;
draw - > AddLine ( wpos + ImVec2 ( pr1 + rsz , offset + round ( tsz . y / 4 ) ) , wpos + ImVec2 ( pr1 + rsz , offset + round ( 3 * tsz . y / 4 ) ) , 0xAAFFFFFF ) ;
draw - > AddLine ( wpos + ImVec2 ( pr1 - rsz , offset + round ( tsz . y / 4 ) ) , wpos + ImVec2 ( pr1 - rsz , offset + round ( 3 * tsz . y / 4 ) ) , 0xAAFFFFFF ) ;
}
if ( tsz . x < zsz )
{
const auto x = ( ev . gpuStart - m_zvStart ) * pxns + ( ( end - ev . gpuStart ) * pxns - tsz . x ) / 2 ;
if ( x < 0 | | x > w - tsz . x )
{
2017-11-18 12:40:49 +00:00
ImGui : : PushClipRect ( wpos + ImVec2 ( px0 , offset ) , wpos + ImVec2 ( px1 , offset + tsz . y * 2 ) , true ) ;
2017-11-25 14:45:16 +00:00
DrawTextContrast ( draw , wpos + ImVec2 ( std : : max ( std : : max ( 0. , px0 ) , std : : min ( double ( w - tsz . x ) , x ) ) , offset ) , 0xFFFFFFFF , zoneName ) ;
2017-11-11 21:56:05 +00:00
ImGui : : PopClipRect ( ) ;
}
2017-11-18 12:40:49 +00:00
else if ( ev . gpuStart = = ev . gpuEnd )
{
2017-11-25 14:45:16 +00:00
DrawTextContrast ( draw , wpos + ImVec2 ( px0 + ( px1 - px0 - tsz . x ) * 0.5 , offset ) , 0xFFFFFFFF , zoneName ) ;
2017-11-18 12:40:49 +00:00
}
2017-11-11 21:56:05 +00:00
else
{
2017-11-25 14:45:16 +00:00
DrawTextContrast ( draw , wpos + ImVec2 ( x , offset ) , 0xFFFFFFFF , zoneName ) ;
2017-11-11 21:56:05 +00:00
}
}
else
{
2017-11-18 12:40:49 +00:00
ImGui : : PushClipRect ( wpos + ImVec2 ( px0 , offset ) , wpos + ImVec2 ( px1 , offset + tsz . y * 2 ) , true ) ;
2017-11-25 14:45:16 +00:00
DrawTextContrast ( draw , wpos + ImVec2 ( ( ev . gpuStart - m_zvStart ) * pxns , offset ) , 0xFFFFFFFF , zoneName ) ;
2017-11-11 21:56:05 +00:00
ImGui : : PopClipRect ( ) ;
}
2017-11-18 12:40:49 +00:00
if ( hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( px0 , offset ) , wpos + ImVec2 ( px1 , offset + tsz . y ) ) )
2017-11-11 21:56:05 +00:00
{
ZoneTooltip ( ev ) ;
2017-11-27 21:41:30 +00:00
if ( ! m_zoomAnim . active & & ImGui : : IsMouseClicked ( 2 ) )
2017-11-11 21:56:05 +00:00
{
ZoomToZone ( ev ) ;
}
2017-11-12 00:25:44 +00:00
if ( ImGui : : IsMouseClicked ( 0 ) )
{
m_zoneInfoWindow = nullptr ;
m_gpuInfoWindow = & ev ;
2017-11-13 23:48:26 +00:00
m_gpuInfoWindowThread = thread ;
2017-11-12 00:25:44 +00:00
}
2017-11-11 22:13:54 +00:00
2017-11-13 23:48:26 +00:00
m_gpuThread = thread ;
2017-11-11 22:13:54 +00:00
m_gpuStart = ev . cpuStart ;
m_gpuEnd = ev . cpuEnd ;
2017-11-11 21:56:05 +00:00
}
+ + it ;
}
}
return maxdepth ;
}
2017-12-05 21:09:53 +00:00
static inline uint64_t GetThreadBit ( uint8_t thread )
2017-10-08 21:03:38 +00:00
{
2017-12-05 21:09:53 +00:00
return uint64_t ( 1 ) < < thread ;
2017-10-08 21:03:38 +00:00
}
2017-12-05 21:09:53 +00:00
static inline bool IsThreadWaiting ( uint64_t bitlist , uint64_t threadBit )
2017-10-28 10:48:05 +00:00
{
2017-12-05 21:09:53 +00:00
return ( bitlist & threadBit ) ! = 0 ;
}
static inline bool AreOtherWaiting ( uint64_t bitlist , uint64_t threadBit )
{
return ( bitlist & ~ threadBit ) ! = 0 ;
2017-10-28 10:48:05 +00:00
}
2017-10-28 11:44:46 +00:00
enum class LockState
{
2017-11-26 20:37:57 +00:00
Nothing ,
HasLock , // green
HasBlockingLock , // yellow
WaitLock // red
2017-10-28 11:44:46 +00:00
} ;
2018-02-13 13:57:47 +00:00
static Vector < LockEvent * > : : const_iterator GetNextLockEvent ( const Vector < LockEvent * > : : const_iterator & it , const Vector < LockEvent * > : : const_iterator & end , LockState & nextState , uint64_t threadBit )
2017-10-04 19:27:06 +00:00
{
2017-10-28 11:44:46 +00:00
auto next = it ;
next + + ;
2017-12-17 17:00:15 +00:00
switch ( nextState )
{
case LockState : : Nothing :
while ( next < end )
{
if ( ( * next ) - > lockCount ! = 0 )
{
if ( GetThreadBit ( ( * next ) - > lockingThread ) = = threadBit )
{
nextState = AreOtherWaiting ( ( * next ) - > waitList , threadBit ) ? LockState : : HasBlockingLock : LockState : : HasLock ;
break ;
}
else if ( IsThreadWaiting ( ( * next ) - > waitList , threadBit ) )
{
nextState = LockState : : WaitLock ;
break ;
}
}
next + + ;
}
break ;
case LockState : : HasLock :
while ( next < end )
{
if ( ( * next ) - > lockCount = = 0 )
{
nextState = LockState : : Nothing ;
break ;
}
if ( ( * next ) - > waitList ! = 0 )
{
if ( AreOtherWaiting ( ( * next ) - > waitList , threadBit ) )
{
nextState = LockState : : HasBlockingLock ;
}
break ;
}
if ( ( * next ) - > waitList ! = ( * it ) - > waitList | | ( * next ) - > lockCount ! = ( * it ) - > lockCount )
{
break ;
}
next + + ;
}
break ;
case LockState : : HasBlockingLock :
while ( next < end )
{
if ( ( * next ) - > lockCount = = 0 )
{
nextState = LockState : : Nothing ;
break ;
}
if ( ( * next ) - > waitList ! = ( * it ) - > waitList | | ( * next ) - > lockCount ! = ( * it ) - > lockCount )
{
break ;
}
next + + ;
}
break ;
case LockState : : WaitLock :
while ( next < end )
{
if ( GetThreadBit ( ( * next ) - > lockingThread ) = = threadBit )
{
nextState = AreOtherWaiting ( ( * next ) - > waitList , threadBit ) ? LockState : : HasBlockingLock : LockState : : HasLock ;
break ;
}
if ( ( * next ) - > lockingThread ! = ( * it ) - > lockingThread )
{
break ;
}
if ( ( * next ) - > lockCount = = 0 )
{
break ;
}
next + + ;
}
break ;
default :
assert ( false ) ;
break ;
}
return next ;
}
2018-02-13 13:57:47 +00:00
static Vector < LockEvent * > : : const_iterator GetNextLockEventShared ( const Vector < LockEvent * > : : const_iterator & it , const Vector < LockEvent * > : : const_iterator & end , LockState & nextState , uint64_t threadBit )
2017-12-17 17:00:15 +00:00
{
2017-12-17 17:44:31 +00:00
const auto itptr = ( const LockEventShared * ) * it ;
2017-12-17 17:00:15 +00:00
auto next = it ;
next + + ;
2017-12-09 18:28:12 +00:00
switch ( nextState )
2017-10-05 21:18:24 +00:00
{
2017-10-28 11:44:46 +00:00
case LockState : : Nothing :
while ( next < end )
{
2017-12-17 17:44:31 +00:00
const auto ptr = ( const LockEventShared * ) * next ;
if ( ptr - > lockCount ! = 0 )
2017-10-28 11:44:46 +00:00
{
2017-12-17 17:44:31 +00:00
const auto wait = ptr - > waitList | ptr - > waitShared ;
if ( GetThreadBit ( ptr - > lockingThread ) = = threadBit )
2017-10-28 11:44:46 +00:00
{
2017-12-10 22:33:39 +00:00
nextState = AreOtherWaiting ( wait , threadBit ) ? LockState : : HasBlockingLock : LockState : : HasLock ;
2017-10-28 11:44:46 +00:00
break ;
}
2017-12-10 22:33:39 +00:00
else if ( IsThreadWaiting ( wait , threadBit ) )
2017-10-28 11:44:46 +00:00
{
nextState = LockState : : WaitLock ;
break ;
}
}
2017-12-17 17:44:31 +00:00
else if ( IsThreadWaiting ( ptr - > sharedList , threadBit ) )
2017-12-10 22:30:13 +00:00
{
2017-12-17 17:44:31 +00:00
nextState = ( ptr - > waitList ! = 0 ) ? LockState : : HasBlockingLock : LockState : : HasLock ;
2017-12-10 22:30:13 +00:00
break ;
}
2017-12-17 17:44:31 +00:00
else if ( ptr - > sharedList ! = 0 & & IsThreadWaiting ( ptr - > waitList , threadBit ) )
2017-12-10 22:30:13 +00:00
{
nextState = LockState : : WaitLock ;
break ;
}
2017-10-28 11:44:46 +00:00
next + + ;
}
break ;
case LockState : : HasLock :
while ( next < end )
{
2017-12-17 17:44:31 +00:00
const auto ptr = ( const LockEventShared * ) * next ;
if ( ptr - > lockCount = = 0 & & ! IsThreadWaiting ( ptr - > sharedList , threadBit ) )
2017-10-28 11:44:46 +00:00
{
nextState = LockState : : Nothing ;
break ;
}
2017-12-17 17:44:31 +00:00
if ( ptr - > waitList ! = 0 )
2017-10-28 11:44:46 +00:00
{
2017-12-17 17:44:31 +00:00
if ( AreOtherWaiting ( ptr - > waitList , threadBit ) )
2017-10-28 11:44:46 +00:00
{
nextState = LockState : : HasBlockingLock ;
}
break ;
}
2017-12-17 17:44:31 +00:00
else if ( ! IsThreadWaiting ( ptr - > sharedList , threadBit ) & & ptr - > waitShared ! = 0 )
2017-12-10 22:30:13 +00:00
{
nextState = LockState : : HasBlockingLock ;
break ;
}
2017-12-17 17:44:31 +00:00
if ( ptr - > waitList ! = itptr - > waitList | | ptr - > waitShared ! = itptr - > waitShared | | ptr - > lockCount ! = itptr - > lockCount | | ptr - > sharedList ! = itptr - > sharedList )
2017-10-28 11:44:46 +00:00
{
break ;
}
next + + ;
}
break ;
case LockState : : HasBlockingLock :
while ( next < end )
{
2017-12-17 17:44:31 +00:00
const auto ptr = ( const LockEventShared * ) * next ;
if ( ptr - > lockCount = = 0 & & ! IsThreadWaiting ( ptr - > sharedList , threadBit ) )
2017-10-28 11:44:46 +00:00
{
nextState = LockState : : Nothing ;
break ;
}
2017-12-17 17:44:31 +00:00
if ( ptr - > waitList ! = itptr - > waitList | | ptr - > waitShared ! = itptr - > waitShared | | ptr - > lockCount ! = itptr - > lockCount | | ptr - > sharedList ! = itptr - > sharedList )
2017-10-28 11:44:46 +00:00
{
break ;
}
next + + ;
}
break ;
case LockState : : WaitLock :
while ( next < end )
{
2017-12-17 17:44:31 +00:00
const auto ptr = ( const LockEventShared * ) * next ;
if ( GetThreadBit ( ptr - > lockingThread ) = = threadBit )
2017-10-28 11:44:46 +00:00
{
2017-12-17 17:44:31 +00:00
const auto wait = ptr - > waitList | ptr - > waitShared ;
2017-12-10 22:33:39 +00:00
nextState = AreOtherWaiting ( wait , threadBit ) ? LockState : : HasBlockingLock : LockState : : HasLock ;
2017-12-10 22:30:13 +00:00
break ;
}
2017-12-17 17:44:31 +00:00
if ( IsThreadWaiting ( ptr - > sharedList , threadBit ) )
2017-12-10 22:30:13 +00:00
{
2017-12-17 17:44:31 +00:00
nextState = ( ptr - > waitList ! = 0 ) ? LockState : : HasBlockingLock : LockState : : HasLock ;
2017-10-28 11:44:46 +00:00
break ;
}
2017-12-17 17:44:31 +00:00
if ( ptr - > lockingThread ! = itptr - > lockingThread )
2017-10-28 11:44:46 +00:00
{
break ;
}
2017-12-17 17:44:31 +00:00
if ( ptr - > lockCount = = 0 & & ! IsThreadWaiting ( ptr - > waitShared , threadBit ) )
2017-10-28 11:44:46 +00:00
{
break ;
}
next + + ;
}
break ;
default :
assert ( false ) ;
break ;
}
return next ;
}
2017-10-05 21:18:24 +00:00
2017-10-28 13:15:07 +00:00
static LockState CombineLockState ( LockState state , LockState next )
{
2017-11-26 20:37:57 +00:00
return ( LockState ) std : : max ( ( int ) state , ( int ) next ) ;
2017-10-28 13:15:07 +00:00
}
2017-10-28 11:44:46 +00:00
int View : : DrawLocks ( uint64_t tid , bool hover , double pxns , const ImVec2 & wpos , int _offset , LockHighlight & highlight )
{
2018-02-13 13:57:47 +00:00
const auto delay = m_worker . GetDelay ( ) ;
const auto resolution = m_worker . GetResolution ( ) ;
2017-10-28 12:25:35 +00:00
const auto w = ImGui : : GetWindowContentRegionWidth ( ) ;
const auto ty = ImGui : : GetFontSize ( ) ;
const auto ostep = ty + 1 ;
auto draw = ImGui : : GetWindowDrawList ( ) ;
2018-02-13 13:57:47 +00:00
const auto dsz = delay * pxns ;
const auto rsz = resolution * pxns ;
2017-10-28 12:25:35 +00:00
2017-10-04 19:27:06 +00:00
int cnt = 0 ;
2018-02-13 13:57:47 +00:00
for ( const auto & v : m_worker . GetLockMap ( ) )
2017-10-04 19:27:06 +00:00
{
2018-02-13 13:57:47 +00:00
const auto & lockmap = v . second ;
2018-03-20 14:41:06 +00:00
if ( ! lockmap . valid | | ! Visible ( & lockmap ) ) continue ;
2017-10-22 11:25:58 +00:00
2017-10-08 21:03:38 +00:00
auto it = lockmap . threadMap . find ( tid ) ;
if ( it = = lockmap . threadMap . end ( ) ) continue ;
2018-02-13 13:57:47 +00:00
const auto & tl = lockmap . timeline ;
2017-10-05 21:18:24 +00:00
assert ( ! tl . empty ( ) ) ;
2017-10-06 16:52:52 +00:00
if ( tl . back ( ) - > time < m_zvStart ) continue ;
2017-10-08 21:03:38 +00:00
2017-12-17 17:00:15 +00:00
auto GetNextLockFunc = lockmap . type = = LockType : : Lockable ? GetNextLockEvent : GetNextLockEventShared ;
2017-10-08 21:03:38 +00:00
const auto thread = it - > second ;
2017-12-05 21:09:53 +00:00
const auto threadBit = GetThreadBit ( thread ) ;
2017-10-08 21:03:38 +00:00
2018-02-13 13:57:47 +00:00
auto vbegin = std : : lower_bound ( tl . begin ( ) , tl . end ( ) , m_zvStart - delay , [ ] ( const auto & l , const auto & r ) { return l - > time < r ; } ) ;
const auto vend = std : : lower_bound ( vbegin , tl . end ( ) , m_zvEnd + resolution , [ ] ( const auto & l , const auto & r ) { return l - > time < r ; } ) ;
2017-10-05 21:18:24 +00:00
if ( vbegin > tl . begin ( ) ) vbegin - - ;
bool drawn = false ;
2018-02-13 13:57:47 +00:00
const auto & srcloc = m_worker . GetSourceLocation ( lockmap . srcloc ) ;
2017-10-28 12:25:35 +00:00
const auto offset = _offset + ostep * cnt ;
2017-10-04 19:27:06 +00:00
2017-10-28 11:44:46 +00:00
LockState state = LockState : : Nothing ;
2017-12-17 17:00:15 +00:00
if ( lockmap . type = = LockType : : Lockable )
2017-10-08 21:03:38 +00:00
{
2017-12-17 17:00:15 +00:00
if ( ( * vbegin ) - > lockCount ! = 0 )
2017-10-08 21:03:38 +00:00
{
2017-12-17 17:00:15 +00:00
if ( ( * vbegin ) - > lockingThread = = thread )
{
state = AreOtherWaiting ( ( * vbegin ) - > waitList , threadBit ) ? LockState : : HasBlockingLock : LockState : : HasLock ;
}
else if ( IsThreadWaiting ( ( * vbegin ) - > waitList , threadBit ) )
{
state = LockState : : WaitLock ;
}
2017-10-08 21:03:38 +00:00
}
2017-12-17 17:00:15 +00:00
}
else
{
2017-12-17 17:44:31 +00:00
const auto ptr = ( LockEventShared * ) * vbegin ;
if ( ptr - > lockCount ! = 0 )
2017-12-17 17:00:15 +00:00
{
2017-12-17 17:44:31 +00:00
if ( ptr - > lockingThread = = thread )
2017-12-17 17:00:15 +00:00
{
2017-12-17 17:44:31 +00:00
state = ( AreOtherWaiting ( ptr - > waitList , threadBit ) | | AreOtherWaiting ( ptr - > waitShared , threadBit ) ) ? LockState : : HasBlockingLock : LockState : : HasLock ;
2017-12-17 17:00:15 +00:00
}
2017-12-17 17:44:31 +00:00
else if ( IsThreadWaiting ( ptr - > waitList , threadBit ) | | IsThreadWaiting ( ptr - > waitShared , threadBit ) )
2017-12-17 17:00:15 +00:00
{
state = LockState : : WaitLock ;
}
}
2017-12-17 17:44:31 +00:00
else if ( IsThreadWaiting ( ptr - > sharedList , threadBit ) )
2017-12-17 17:00:15 +00:00
{
2017-12-17 17:44:31 +00:00
state = ptr - > waitList ! = 0 ? LockState : : HasBlockingLock : LockState : : HasLock ;
2017-12-17 17:00:15 +00:00
}
2017-12-17 17:44:31 +00:00
else if ( ptr - > sharedList ! = 0 & & IsThreadWaiting ( ptr - > waitList , threadBit ) )
2017-10-08 21:03:38 +00:00
{
2017-10-28 11:44:46 +00:00
state = LockState : : WaitLock ;
2017-10-08 21:03:38 +00:00
}
}
2017-10-28 20:44:41 +00:00
double pxend = 0 ;
2017-10-28 12:15:18 +00:00
for ( ; ; )
2017-10-05 21:18:24 +00:00
{
2017-10-28 12:14:26 +00:00
while ( vbegin < vend & & ( state = = LockState : : Nothing | | ( m_onlyContendedLocks & & state = = LockState : : HasLock ) ) )
2017-10-28 11:56:35 +00:00
{
2017-12-17 17:00:15 +00:00
vbegin = GetNextLockFunc ( vbegin , vend , state , threadBit ) ;
2017-10-28 11:56:35 +00:00
}
2017-10-28 12:14:26 +00:00
if ( vbegin > = vend ) break ;
2017-10-28 11:56:35 +00:00
2017-10-28 13:15:07 +00:00
assert ( state ! = LockState : : Nothing & & ( ! m_onlyContendedLocks | | state ! = LockState : : HasLock ) ) ;
drawn = true ;
LockState drawState = state ;
2017-12-17 17:00:15 +00:00
auto next = GetNextLockFunc ( vbegin , vend , state , threadBit ) ;
2017-10-05 21:18:24 +00:00
2017-10-28 12:08:10 +00:00
const auto t0 = ( * vbegin ) - > time ;
2017-12-09 19:05:34 +00:00
int64_t t1 = next = = tl . end ( ) ? m_lastTime : ( * next ) - > time ;
2017-10-28 20:44:41 +00:00
const auto px0 = std : : max ( pxend , ( t0 - m_zvStart ) * pxns ) ;
2017-10-28 13:29:25 +00:00
auto tx0 = px0 ;
2017-10-28 13:15:07 +00:00
double px1 = ( t1 - m_zvStart ) * pxns ;
2017-10-28 13:33:34 +00:00
uint64_t condensed = 0 ;
2017-10-28 13:15:07 +00:00
for ( ; ; )
{
2017-10-28 13:29:25 +00:00
if ( next > = vend | | px1 - tx0 > MinVisSize ) break ;
2017-10-28 13:15:07 +00:00
auto n = next ;
2017-12-09 18:24:35 +00:00
auto ns = state ;
2017-10-28 13:15:07 +00:00
while ( n < vend & & ( ns = = LockState : : Nothing | | ( m_onlyContendedLocks & & ns = = LockState : : HasLock ) ) )
{
2017-12-17 17:00:15 +00:00
n = GetNextLockFunc ( n , vend , ns , threadBit ) ;
2017-10-28 13:15:07 +00:00
}
2017-10-28 13:24:25 +00:00
if ( n > = vend ) break ;
if ( n = = next )
{
2017-12-17 17:00:15 +00:00
n = GetNextLockFunc ( n , vend , ns , threadBit ) ;
2017-10-28 13:24:25 +00:00
}
2017-12-09 18:24:35 +00:00
drawState = CombineLockState ( drawState , state ) ;
2017-10-28 20:34:52 +00:00
condensed + + ;
2017-12-09 19:05:34 +00:00
const auto t2 = n = = tl . end ( ) ? m_lastTime : ( * n ) - > time ;
2017-10-28 13:15:07 +00:00
const auto px2 = ( t2 - m_zvStart ) * pxns ;
2017-10-28 13:29:25 +00:00
if ( px2 - px1 > MinVisSize ) break ;
2017-10-28 13:48:05 +00:00
if ( drawState ! = ns & & px2 - px0 > MinVisSize & & ! ( ns = = LockState : : Nothing | | ( m_onlyContendedLocks & & ns = = LockState : : HasLock ) ) ) break ;
2017-10-28 13:15:07 +00:00
t1 = t2 ;
2017-10-28 13:29:25 +00:00
tx0 = px1 ;
2017-10-28 13:15:07 +00:00
px1 = px2 ;
next = n ;
2017-12-09 18:24:35 +00:00
state = ns ;
2017-10-28 13:15:07 +00:00
}
2017-10-28 12:08:10 +00:00
2017-11-18 12:40:49 +00:00
pxend = std : : max ( { px1 , px0 + MinVisSize , px0 + pxns * 0.5 } ) ;
2017-10-28 20:44:41 +00:00
bool itemHovered = hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( std : : max ( px0 , - 10.0 ) , offset ) , wpos + ImVec2 ( std : : min ( pxend , double ( w + 10 ) ) , offset + ty ) ) ;
2017-10-28 12:08:10 +00:00
if ( itemHovered )
2017-10-05 21:18:24 +00:00
{
2017-11-07 21:14:54 +00:00
if ( condensed > 1 )
2017-10-05 21:35:21 +00:00
{
2017-10-28 13:33:34 +00:00
ImGui : : BeginTooltip ( ) ;
2017-11-25 12:50:41 +00:00
ImGui : : Text ( " Multiple lock events (%s) " , RealToString ( condensed , true ) ) ;
2017-10-28 13:33:34 +00:00
ImGui : : EndTooltip ( ) ;
2017-10-28 12:08:10 +00:00
}
else
{
2017-10-28 13:33:34 +00:00
highlight . blocked = drawState = = LockState : : HasBlockingLock ;
if ( ! highlight . blocked )
2017-10-08 21:03:38 +00:00
{
2017-10-28 13:33:34 +00:00
highlight . id = v . first ;
highlight . begin = t0 ;
highlight . end = t1 ;
highlight . thread = thread ;
highlight . blocked = false ;
2017-10-08 21:03:38 +00:00
}
2017-10-28 13:33:34 +00:00
else
2017-10-08 21:03:38 +00:00
{
2017-10-28 13:33:34 +00:00
auto b = vbegin ;
while ( b ! = tl . begin ( ) )
2017-10-08 21:03:38 +00:00
{
2017-10-28 13:33:34 +00:00
if ( ( * b ) - > lockingThread ! = ( * vbegin ) - > lockingThread )
{
break ;
}
b - - ;
2017-10-08 21:03:38 +00:00
}
2017-10-28 13:33:34 +00:00
b + + ;
highlight . begin = ( * b ) - > time ;
2017-10-08 21:03:38 +00:00
2017-10-28 13:33:34 +00:00
auto e = next ;
while ( e ! = tl . end ( ) )
2017-10-08 21:03:38 +00:00
{
2017-10-28 13:33:34 +00:00
if ( ( * e ) - > lockingThread ! = ( * next ) - > lockingThread )
{
highlight . id = v . first ;
highlight . end = ( * e ) - > time ;
highlight . thread = thread ;
break ;
}
e + + ;
2017-10-08 21:03:38 +00:00
}
}
2017-10-28 13:33:34 +00:00
ImGui : : BeginTooltip ( ) ;
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " Lock #% " PRIu32 " : %s " , v . first , m_worker . GetString ( srcloc . function ) ) ;
2017-11-17 23:51:04 +00:00
ImGui : : Separator ( ) ;
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " %s:%i " , m_worker . GetString ( srcloc . file ) , srcloc . line ) ;
2017-10-28 13:33:34 +00:00
ImGui : : Text ( " Time: %s " , TimeToString ( t1 - t0 ) ) ;
2017-10-05 21:35:21 +00:00
ImGui : : Separator ( ) ;
2017-10-06 16:12:13 +00:00
2017-10-28 20:14:01 +00:00
uint32_t markloc = 0 ;
2017-10-28 13:33:34 +00:00
auto it = vbegin ;
for ( ; ; )
2017-10-06 16:12:13 +00:00
{
2017-10-28 13:33:34 +00:00
if ( ( * it ) - > thread = = thread )
{
2017-12-05 21:09:53 +00:00
if ( ( ( * it ) - > lockingThread = = thread | | IsThreadWaiting ( ( * it ) - > waitList , threadBit ) ) & & ( * it ) - > srcloc ! = 0 )
2017-10-28 13:33:34 +00:00
{
markloc = ( * it ) - > srcloc ;
break ;
}
}
if ( it = = tl . begin ( ) ) break ;
- - it ;
2017-10-06 16:12:13 +00:00
}
2017-10-28 13:33:34 +00:00
if ( markloc ! = 0 )
2017-10-06 16:12:13 +00:00
{
2018-02-13 13:57:47 +00:00
const auto & marklocdata = m_worker . GetSourceLocation ( markloc ) ;
2017-10-28 13:33:34 +00:00
ImGui : : Text ( " Lock event location: " ) ;
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " %s " , m_worker . GetString ( marklocdata . function ) ) ;
ImGui : : Text ( " %s:%i " , m_worker . GetString ( marklocdata . file ) , marklocdata . line ) ;
2017-10-28 13:33:34 +00:00
ImGui : : Separator ( ) ;
2017-10-06 16:12:13 +00:00
}
2017-10-28 13:33:34 +00:00
2017-12-17 18:40:45 +00:00
if ( v . second . type = = LockType : : Lockable )
2017-10-05 21:35:21 +00:00
{
2017-12-17 18:40:45 +00:00
switch ( drawState )
2017-10-28 13:33:34 +00:00
{
2017-12-17 18:40:45 +00:00
case LockState : : HasLock :
if ( ( * vbegin ) - > lockCount = = 1 )
{
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " Thread \" %s \" has lock. No other threads are waiting. " , m_worker . GetThreadString ( tid ) ) ;
2017-12-17 18:40:45 +00:00
}
else
{
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " Thread \" %s \" has %i locks. No other threads are waiting. " , m_worker . GetThreadString ( tid ) , ( * vbegin ) - > lockCount ) ;
2017-12-17 18:40:45 +00:00
}
if ( ( * vbegin ) - > waitList ! = 0 )
{
assert ( ! AreOtherWaiting ( ( * next ) - > waitList , threadBit ) ) ;
ImGui : : Text ( " Recursive lock acquire in thread. " ) ;
}
break ;
case LockState : : HasBlockingLock :
2017-10-28 13:33:34 +00:00
{
2017-12-17 18:40:45 +00:00
if ( ( * vbegin ) - > lockCount = = 1 )
{
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " Thread \" %s \" has lock. Blocked threads (%i): " , m_worker . GetThreadString ( tid ) , TracyCountBits ( ( * vbegin ) - > waitList ) ) ;
2017-12-17 18:40:45 +00:00
}
else
{
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " Thread \" %s \" has %i locks. Blocked threads (%i): " , m_worker . GetThreadString ( tid ) , ( * vbegin ) - > lockCount , TracyCountBits ( ( * vbegin ) - > waitList ) ) ;
2017-12-17 18:40:45 +00:00
}
auto waitList = ( * vbegin ) - > waitList ;
int t = 0 ;
ImGui : : Indent ( ty ) ;
while ( waitList ! = 0 )
{
if ( waitList & 0x1 )
{
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " \" %s \" " , m_worker . GetThreadString ( lockmap . threadList [ t ] ) ) ;
2017-12-17 18:40:45 +00:00
}
waitList > > = 1 ;
t + + ;
}
ImGui : : Unindent ( ty ) ;
break ;
2017-10-28 13:33:34 +00:00
}
2017-12-17 18:40:45 +00:00
case LockState : : WaitLock :
2017-10-28 13:33:34 +00:00
{
2017-12-17 18:40:45 +00:00
if ( ( * vbegin ) - > lockCount > 0 )
{
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " Thread \" %s \" is blocked by other thread: " , m_worker . GetThreadString ( tid ) ) ;
2017-12-17 18:40:45 +00:00
}
else
{
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " Thread \" %s \" waits to obtain lock after release by thread: " , m_worker . GetThreadString ( tid ) ) ;
2017-12-17 18:40:45 +00:00
}
ImGui : : Indent ( ty ) ;
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " \" %s \" " , m_worker . GetThreadString ( lockmap . threadList [ ( * vbegin ) - > lockingThread ] ) ) ;
2017-12-17 18:40:45 +00:00
ImGui : : Unindent ( ty ) ;
break ;
2017-10-28 13:33:34 +00:00
}
2017-12-17 18:40:45 +00:00
default :
assert ( false ) ;
break ;
2017-10-28 13:33:34 +00:00
}
2017-12-17 18:40:45 +00:00
}
else
{
const auto ptr = ( const LockEventShared * ) * vbegin ;
switch ( drawState )
2017-10-28 13:33:34 +00:00
{
2017-12-17 18:40:45 +00:00
case LockState : : HasLock :
assert ( ptr - > waitList = = 0 ) ;
if ( ptr - > sharedList = = 0 )
{
assert ( ptr - > lockCount = = 1 ) ;
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " Thread \" %s \" has lock. No other threads are waiting. " , m_worker . GetThreadString ( tid ) ) ;
2017-12-17 18:40:45 +00:00
}
else if ( TracyCountBits ( ptr - > sharedList ) = = 1 )
{
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " Thread \" %s \" has a sole shared lock. No other threads are waiting. " , m_worker . GetThreadString ( tid ) ) ;
2017-12-17 18:40:45 +00:00
}
else
{
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " Thread \" %s \" has shared lock. No other threads are waiting. " , m_worker . GetThreadString ( tid ) ) ;
2017-12-17 18:40:45 +00:00
ImGui : : Text ( " Threads sharing the lock (%i): " , TracyCountBits ( ptr - > sharedList ) - 1 ) ;
auto sharedList = ptr - > sharedList ;
int t = 0 ;
ImGui : : Indent ( ty ) ;
while ( sharedList ! = 0 )
{
if ( sharedList & 0x1 & & t ! = thread )
{
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " \" %s \" " , m_worker . GetThreadString ( lockmap . threadList [ t ] ) ) ;
2017-12-17 18:40:45 +00:00
}
sharedList > > = 1 ;
t + + ;
}
ImGui : : Unindent ( ty ) ;
}
break ;
case LockState : : HasBlockingLock :
2017-10-28 13:33:34 +00:00
{
2017-12-17 18:40:45 +00:00
if ( ptr - > sharedList = = 0 )
{
assert ( ptr - > lockCount = = 1 ) ;
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " Thread \" %s \" has lock. Blocked threads (%i): " , m_worker . GetThreadString ( tid ) , TracyCountBits ( ptr - > waitList ) + TracyCountBits ( ptr - > waitShared ) ) ;
2017-12-17 18:40:45 +00:00
}
else if ( TracyCountBits ( ptr - > sharedList ) = = 1 )
{
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " Thread \" %s \" has a sole shared lock. Blocked threads (%i): " , m_worker . GetThreadString ( tid ) , TracyCountBits ( ptr - > waitList ) + TracyCountBits ( ptr - > waitShared ) ) ;
2017-12-17 18:40:45 +00:00
}
else
2017-10-28 13:33:34 +00:00
{
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " Thread \" %s \" has shared lock. " , m_worker . GetThreadString ( tid ) ) ;
2017-12-17 18:40:45 +00:00
ImGui : : Text ( " Threads sharing the lock (%i): " , TracyCountBits ( ptr - > sharedList ) - 1 ) ;
auto sharedList = ptr - > sharedList ;
int t = 0 ;
ImGui : : Indent ( ty ) ;
while ( sharedList ! = 0 )
{
if ( sharedList & 0x1 & & t ! = thread )
{
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " \" %s \" " , m_worker . GetThreadString ( lockmap . threadList [ t ] ) ) ;
2017-12-17 18:40:45 +00:00
}
sharedList > > = 1 ;
t + + ;
}
ImGui : : Unindent ( ty ) ;
ImGui : : Text ( " Blocked threads (%i): " , TracyCountBits ( ptr - > waitList ) + TracyCountBits ( ptr - > waitShared ) ) ;
2017-10-28 13:33:34 +00:00
}
2017-12-17 18:40:45 +00:00
auto waitList = ptr - > waitList ;
int t = 0 ;
ImGui : : Indent ( ty ) ;
while ( waitList ! = 0 )
{
if ( waitList & 0x1 )
{
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " \" %s \" " , m_worker . GetThreadString ( lockmap . threadList [ t ] ) ) ;
2017-12-17 18:40:45 +00:00
}
waitList > > = 1 ;
t + + ;
}
auto waitShared = ptr - > waitShared ;
t = 0 ;
while ( waitShared ! = 0 )
{
if ( waitShared & 0x1 )
{
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " \" %s \" " , m_worker . GetThreadString ( lockmap . threadList [ t ] ) ) ;
2017-12-17 18:40:45 +00:00
}
waitShared > > = 1 ;
t + + ;
}
ImGui : : Unindent ( ty ) ;
break ;
2017-10-28 13:33:34 +00:00
}
2017-12-17 18:40:45 +00:00
case LockState : : WaitLock :
2017-12-10 19:53:20 +00:00
{
2017-12-17 18:40:45 +00:00
assert ( ptr - > lockCount = = 0 | | ptr - > lockCount = = 1 ) ;
if ( ptr - > lockCount ! = 0 | | ptr - > sharedList ! = 0 )
{
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " Thread \" %s \" is blocked by other threads (%i): " , m_worker . GetThreadString ( tid ) , ptr - > lockCount + TracyCountBits ( ptr - > sharedList ) ) ;
2017-12-17 18:40:45 +00:00
}
else
{
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " Thread \" %s \" waits to obtain lock after release by thread: " , m_worker . GetThreadString ( tid ) ) ;
2017-12-17 18:40:45 +00:00
}
ImGui : : Indent ( ty ) ;
if ( ptr - > lockCount ! = 0 )
{
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " \" %s \" " , m_worker . GetThreadString ( lockmap . threadList [ ptr - > lockingThread ] ) ) ;
2017-12-17 18:40:45 +00:00
}
auto sharedList = ptr - > sharedList ;
int t = 0 ;
while ( sharedList ! = 0 )
{
if ( sharedList & 0x1 )
{
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " \" %s \" " , m_worker . GetThreadString ( lockmap . threadList [ t ] ) ) ;
2017-12-17 18:40:45 +00:00
}
sharedList > > = 1 ;
t + + ;
}
ImGui : : Unindent ( ty ) ;
break ;
2017-12-10 19:53:20 +00:00
}
2017-12-17 18:40:45 +00:00
default :
assert ( false ) ;
break ;
2017-12-10 19:53:20 +00:00
}
2017-10-05 21:35:21 +00:00
}
2017-10-28 13:33:34 +00:00
ImGui : : EndTooltip ( ) ;
2017-10-06 16:25:30 +00:00
}
2017-10-28 12:08:10 +00:00
}
2017-10-06 16:25:30 +00:00
2017-10-28 13:15:07 +00:00
const auto cfilled = drawState = = LockState : : HasLock ? 0xFF228A22 : ( drawState = = LockState : : HasBlockingLock ? 0xFF228A8A : 0xFF2222BD ) ;
2017-11-07 20:46:05 +00:00
draw - > AddRectFilled ( wpos + ImVec2 ( std : : max ( px0 , - 10.0 ) , offset ) , wpos + ImVec2 ( std : : min ( pxend , double ( w + 10 ) ) , offset + ty ) , cfilled ) ;
2017-10-28 19:50:06 +00:00
if ( m_lockHighlight . thread ! = thread & & ( drawState = = LockState : : HasBlockingLock ) ! = m_lockHighlight . blocked & & next ! = tl . end ( ) & & m_lockHighlight . id = = int64_t ( v . first ) & & m_lockHighlight . begin < = ( * vbegin ) - > time & & m_lockHighlight . end > = ( * next ) - > time )
2017-10-28 12:08:10 +00:00
{
const auto t = uint8_t ( ( sin ( std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( std : : chrono : : system_clock : : now ( ) . time_since_epoch ( ) ) . count ( ) * 0.01 ) * 0.5 + 0.5 ) * 255 ) ;
2017-11-07 20:46:05 +00:00
draw - > AddRect ( wpos + ImVec2 ( std : : max ( px0 , - 10.0 ) , offset ) , wpos + ImVec2 ( std : : min ( pxend , double ( w + 10 ) ) , offset + ty ) , 0x00FFFFFF | ( t < < 24 ) , 0.f , - 1 , 2.f ) ;
2017-10-28 12:08:10 +00:00
}
2017-10-28 13:33:34 +00:00
else if ( condensed = = 0 )
2017-10-28 12:08:10 +00:00
{
2017-10-28 13:15:07 +00:00
const auto coutline = drawState = = LockState : : HasLock ? 0xFF3BA33B : ( drawState = = LockState : : HasBlockingLock ? 0xFF3BA3A3 : 0xFF3B3BD6 ) ;
2017-11-07 20:46:05 +00:00
draw - > AddRect ( wpos + ImVec2 ( std : : max ( px0 , - 10.0 ) , offset ) , wpos + ImVec2 ( std : : min ( pxend , double ( w + 10 ) ) , offset + ty ) , coutline ) ;
2017-10-28 12:08:10 +00:00
}
2017-11-07 00:51:30 +00:00
const auto rx0 = ( t0 - m_zvStart ) * pxns ;
2017-10-28 12:08:10 +00:00
if ( dsz > = MinVisSize )
{
2017-11-07 20:46:05 +00:00
draw - > AddRectFilled ( wpos + ImVec2 ( rx0 , offset ) , wpos + ImVec2 ( std : : min ( rx0 + dsz , px1 ) , offset + ty ) , 0x882222DD ) ;
2017-10-28 12:08:10 +00:00
}
if ( rsz > = MinVisSize )
{
2017-11-07 21:02:27 +00:00
draw - > AddLine ( wpos + ImVec2 ( rx0 + rsz , offset + round ( ty / 2 ) ) , wpos + ImVec2 ( rx0 - rsz , offset + round ( ty / 2 ) ) , 0xAAFFFFFF ) ;
draw - > AddLine ( wpos + ImVec2 ( rx0 + rsz , offset + round ( ty / 4 ) ) , wpos + ImVec2 ( rx0 + rsz , offset + round ( 3 * ty / 4 ) ) , 0xAAFFFFFF ) ;
draw - > AddLine ( wpos + ImVec2 ( rx0 - rsz , offset + round ( ty / 4 ) ) , wpos + ImVec2 ( rx0 - rsz , offset + round ( 3 * ty / 4 ) ) , 0xAAFFFFFF ) ;
2017-10-28 12:08:10 +00:00
2017-11-07 21:02:27 +00:00
draw - > AddLine ( wpos + ImVec2 ( px1 + rsz , offset + round ( ty / 2 ) ) , wpos + ImVec2 ( px1 - rsz , offset + round ( ty / 2 ) ) , 0xAAFFFFFF ) ;
draw - > AddLine ( wpos + ImVec2 ( px1 + rsz , offset + round ( ty / 4 ) ) , wpos + ImVec2 ( px1 + rsz , offset + round ( 3 * ty / 4 ) ) , 0xAAFFFFFF ) ;
draw - > AddLine ( wpos + ImVec2 ( px1 - rsz , offset + round ( ty / 4 ) ) , wpos + ImVec2 ( px1 - rsz , offset + round ( 3 * ty / 4 ) ) , 0xAAFFFFFF ) ;
2017-10-04 19:27:06 +00:00
}
2017-10-05 21:18:24 +00:00
vbegin = next ;
}
if ( drawn )
{
char buf [ 1024 ] ;
2018-02-13 13:57:47 +00:00
sprintf ( buf , " % " PRIu32 " : %s " , v . first , m_worker . GetString ( srcloc . function ) ) ;
2017-11-25 14:45:16 +00:00
DrawTextContrast ( draw , wpos + ImVec2 ( 0 , offset ) , 0xFF8888FF , buf ) ;
2017-10-25 22:42:16 +00:00
if ( hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( 0 , offset ) , wpos + ImVec2 ( ty + ImGui : : CalcTextSize ( buf ) . x , offset + ty ) ) )
{
ImGui : : BeginTooltip ( ) ;
2017-12-10 20:49:23 +00:00
switch ( v . second . type )
{
case LockType : : Lockable :
ImGui : : Text ( " Type: lockable " ) ;
break ;
2017-12-10 20:49:45 +00:00
case LockType : : SharedLockable :
ImGui : : Text ( " Type: shared lockable " ) ;
break ;
2017-12-10 20:49:23 +00:00
default :
assert ( false ) ;
break ;
}
2017-10-25 22:42:16 +00:00
ImGui : : Text ( " Thread list: " ) ;
2017-11-17 23:51:04 +00:00
ImGui : : Separator ( ) ;
2017-10-25 22:42:16 +00:00
ImGui : : Indent ( ty ) ;
2018-02-13 13:57:47 +00:00
for ( const auto & t : v . second . threadList )
2017-10-25 22:42:16 +00:00
{
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " %s " , m_worker . GetThreadString ( t ) ) ;
2017-10-25 22:42:16 +00:00
}
ImGui : : Unindent ( ty ) ;
2017-11-25 12:48:03 +00:00
ImGui : : Separator ( ) ;
ImGui : : Text ( " Lock events: %s " , RealToString ( v . second . timeline . size ( ) , true ) ) ;
2017-10-25 22:42:16 +00:00
ImGui : : EndTooltip ( ) ;
}
2017-10-05 21:18:24 +00:00
cnt + + ;
2017-10-04 19:27:06 +00:00
}
}
return cnt ;
}
2017-10-13 13:15:57 +00:00
enum { PlotHeight = 100 } ;
2017-10-13 12:54:32 +00:00
2017-10-13 13:15:57 +00:00
int View : : DrawPlots ( int offset , double pxns , const ImVec2 & wpos , bool hover )
{
2017-11-26 16:27:51 +00:00
enum { MaxPoints = 512 } ;
float tmpvec [ MaxPoints * 2 ] ;
2017-10-13 12:54:32 +00:00
const auto w = ImGui : : GetWindowContentRegionWidth ( ) - 1 ;
const auto ty = ImGui : : GetFontSize ( ) ;
auto draw = ImGui : : GetWindowDrawList ( ) ;
2017-10-13 13:41:20 +00:00
const auto to = 9.f ;
const auto th = ( ty - to ) * sqrt ( 3 ) * 0.5 ;
2017-10-18 20:29:59 +00:00
const auto nspx = 1.0 / pxns ;
2017-10-13 12:54:32 +00:00
2018-02-13 13:57:47 +00:00
for ( const auto & v : m_worker . GetPlots ( ) )
2017-10-13 12:54:32 +00:00
{
2018-02-13 13:57:47 +00:00
if ( ! Visible ( v ) ) continue ;
2017-10-22 11:17:34 +00:00
2017-10-13 13:36:16 +00:00
assert ( ! v - > data . empty ( ) ) ;
2017-10-13 12:54:32 +00:00
2018-02-13 13:57:47 +00:00
bool & showFull = ShowFull ( v ) ;
if ( showFull )
2017-10-13 13:41:20 +00:00
{
draw - > AddTriangleFilled ( wpos + ImVec2 ( to / 2 , offset + to / 2 ) , wpos + ImVec2 ( ty - to / 2 , offset + to / 2 ) , wpos + ImVec2 ( ty * 0.5 , offset + to / 2 + th ) , 0xFF44DDDD ) ;
}
else
{
draw - > AddTriangle ( wpos + ImVec2 ( to / 2 , offset + to / 2 ) , wpos + ImVec2 ( to / 2 , offset + ty - to / 2 ) , wpos + ImVec2 ( to / 2 + th , offset + ty * 0.5 ) , 0xFF226E6E ) ;
}
2018-02-13 13:57:47 +00:00
const auto txt = m_worker . GetString ( v - > name ) ;
draw - > AddText ( wpos + ImVec2 ( ty , offset ) , showFull ? 0xFF44DDDD : 0xFF226E6E , txt ) ;
2017-10-13 12:54:32 +00:00
draw - > AddLine ( wpos + ImVec2 ( 0 , offset + ty - 1 ) , wpos + ImVec2 ( w , offset + ty - 1 ) , 0x8844DDDD ) ;
2017-10-13 13:44:24 +00:00
if ( hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( 0 , offset ) , wpos + ImVec2 ( ty + ImGui : : CalcTextSize ( txt ) . x , offset + ty ) ) )
2017-10-13 13:41:20 +00:00
{
2017-10-13 13:44:24 +00:00
if ( ImGui : : IsMouseClicked ( 0 ) )
{
2018-02-13 13:57:47 +00:00
showFull = ! showFull ;
2017-10-13 13:44:24 +00:00
}
2017-12-05 20:24:09 +00:00
const auto tr = v - > data . back ( ) . time - v - > data . front ( ) . time ;
2017-10-13 13:55:09 +00:00
2017-10-13 13:44:24 +00:00
ImGui : : BeginTooltip ( ) ;
ImGui : : Text ( " Plot \" %s \" " , txt ) ;
2017-11-17 23:51:04 +00:00
ImGui : : Separator ( ) ;
2017-10-19 18:34:48 +00:00
ImGui : : Text ( " Data points: %s " , RealToString ( v - > data . size ( ) , true ) ) ;
2017-10-18 18:33:49 +00:00
ImGui : : Text ( " Data range: %s " , RealToString ( v - > max - v - > min , true ) ) ;
ImGui : : Text ( " Min value: %s " , RealToString ( v - > min , true ) ) ;
ImGui : : Text ( " Max value: %s " , RealToString ( v - > max , true ) ) ;
2017-10-13 13:55:09 +00:00
ImGui : : Text ( " Time range: %s " , TimeToString ( tr ) ) ;
2017-10-28 19:50:06 +00:00
ImGui : : Text ( " Data/second: %s " , RealToString ( double ( v - > data . size ( ) ) / tr * 1000000000ll , true ) ) ;
2017-10-13 13:55:09 +00:00
2017-12-05 20:24:09 +00:00
const auto it = std : : lower_bound ( v - > data . begin ( ) , v - > data . end ( ) , v - > data . back ( ) . time - 1000000000ll * 10 , [ ] ( const auto & l , const auto & r ) { return l . time < r ; } ) ;
const auto tr10 = v - > data . back ( ) . time - it - > time ;
2017-10-13 13:55:09 +00:00
if ( tr10 ! = 0 )
{
2017-10-28 19:50:06 +00:00
ImGui : : Text ( " D/s (10s): %s " , RealToString ( double ( std : : distance ( it , v - > data . end ( ) ) ) / tr10 * 1000000000ll , true ) ) ;
2017-10-13 13:55:09 +00:00
}
2017-10-13 13:44:24 +00:00
ImGui : : EndTooltip ( ) ;
2017-10-13 13:41:20 +00:00
}
2017-10-13 12:54:32 +00:00
2017-10-13 13:41:20 +00:00
offset + = ty ;
2017-10-13 12:54:32 +00:00
2018-02-13 13:57:47 +00:00
if ( showFull )
2017-10-13 12:54:32 +00:00
{
2018-02-13 13:57:47 +00:00
const auto & vec = v - > data ;
auto it = std : : lower_bound ( vec . begin ( ) , vec . end ( ) , m_zvStart - m_worker . GetDelay ( ) , [ ] ( const auto & l , const auto & r ) { return l . time < r ; } ) ;
auto end = std : : lower_bound ( it , vec . end ( ) , m_zvEnd + m_worker . GetResolution ( ) , [ ] ( const auto & l , const auto & r ) { return l . time < r ; } ) ;
2017-10-13 13:41:20 +00:00
if ( end ! = vec . end ( ) ) end + + ;
if ( it ! = vec . begin ( ) ) it - - ;
2017-12-05 20:24:09 +00:00
double min = it - > val ;
double max = it - > val ;
2017-10-21 11:58:55 +00:00
if ( std : : distance ( it , end ) > 1000000 )
{
min = v - > min ;
max = v - > max ;
}
else
2017-10-13 12:54:32 +00:00
{
2017-10-13 13:41:20 +00:00
auto tmp = it ;
2017-10-13 12:54:32 +00:00
+ + tmp ;
2017-12-08 23:15:10 +00:00
const auto sz = end - tmp ;
2018-03-13 15:23:10 +00:00
for ( ptrdiff_t i = 0 ; i < sz ; i + + )
2017-10-13 13:41:20 +00:00
{
2017-12-08 23:15:10 +00:00
min = tmp [ i ] . val < min ? tmp [ i ] . val : min ;
max = tmp [ i ] . val > max ? tmp [ i ] . val : max ;
2017-10-13 13:41:20 +00:00
}
2017-12-08 23:15:10 +00:00
tmp + = sz ;
2017-10-13 12:54:32 +00:00
}
2017-10-13 13:41:20 +00:00
const auto revrange = 1.0 / ( max - min ) ;
2017-10-13 12:54:32 +00:00
2017-10-13 13:41:20 +00:00
if ( it = = vec . begin ( ) )
{
2017-12-05 20:24:09 +00:00
const auto x = ( it - > time - m_zvStart ) * pxns ;
const auto y = PlotHeight - ( it - > val - min ) * revrange * PlotHeight ;
DrawPlotPoint ( wpos , x , y , offset , 0xFF44DDDD , hover , false , it - > val , 0 , false ) ;
2017-10-13 13:41:20 +00:00
}
2017-10-13 12:54:32 +00:00
2017-10-18 20:29:59 +00:00
auto prevx = it ;
auto prevy = it ;
2017-10-13 13:41:20 +00:00
+ + it ;
2017-10-19 19:04:57 +00:00
ptrdiff_t skip = 0 ;
2017-10-13 13:41:20 +00:00
while ( it < end )
{
2017-12-05 20:24:09 +00:00
const auto x0 = ( prevx - > time - m_zvStart ) * pxns ;
const auto x1 = ( it - > time - m_zvStart ) * pxns ;
const auto y0 = PlotHeight - ( prevy - > val - min ) * revrange * PlotHeight ;
const auto y1 = PlotHeight - ( it - > val - min ) * revrange * PlotHeight ;
2017-10-13 12:54:32 +00:00
2017-10-13 13:41:20 +00:00
draw - > AddLine ( wpos + ImVec2 ( x0 , offset + y0 ) , wpos + ImVec2 ( x1 , offset + y1 ) , 0xFF44DDDD ) ;
2017-10-13 12:54:32 +00:00
2017-10-19 19:04:57 +00:00
const auto rx = skip = = 0 ? 2.0 : ( skip = = 1 ? 2.5 : 4.0 ) ;
2017-12-05 20:24:09 +00:00
auto range = std : : upper_bound ( it , end , int64_t ( it - > time + nspx * rx ) , [ ] ( const auto & l , const auto & r ) { return l < r . time ; } ) ;
2017-10-18 20:29:59 +00:00
assert ( range > it ) ;
2017-10-19 17:09:02 +00:00
const auto rsz = std : : distance ( it , range ) ;
if ( rsz = = 1 )
2017-10-18 20:29:59 +00:00
{
2017-12-05 20:24:09 +00:00
DrawPlotPoint ( wpos , x1 , y1 , offset , 0xFF44DDDD , hover , true , it - > val , prevy - > val , false ) ;
2017-10-18 20:29:59 +00:00
prevx = it ;
prevy = it ;
+ + it ;
}
else
{
prevx = it ;
2017-10-21 12:15:33 +00:00
skip = rsz / MaxPoints ;
2017-10-19 19:04:57 +00:00
const auto skip1 = std : : max < ptrdiff_t > ( 1 , skip ) ;
const auto sz = rsz / skip1 + 1 ;
2017-10-21 12:15:33 +00:00
assert ( sz < = MaxPoints * 2 ) ;
2017-10-19 17:43:27 +00:00
2017-10-21 12:15:33 +00:00
auto dst = tmpvec ;
2017-10-19 17:43:27 +00:00
for ( ; ; )
2017-10-18 20:29:59 +00:00
{
2017-12-05 20:24:09 +00:00
* dst + + = float ( it - > val ) ;
2017-10-19 19:04:57 +00:00
if ( std : : distance ( it , range ) > skip1 )
2017-10-19 17:43:27 +00:00
{
2017-10-19 19:04:57 +00:00
it + = skip1 ;
2017-10-19 17:43:27 +00:00
}
else
{
break ;
}
2017-10-18 20:29:59 +00:00
}
2017-12-08 22:11:08 +00:00
pdqsort_branchless ( tmpvec , dst ) ;
2017-10-18 20:29:59 +00:00
2017-10-21 12:15:33 +00:00
draw - > AddLine ( wpos + ImVec2 ( x1 , offset + PlotHeight - ( tmpvec [ 0 ] - min ) * revrange * PlotHeight ) , wpos + ImVec2 ( x1 , offset + PlotHeight - ( dst [ - 1 ] - min ) * revrange * PlotHeight ) , 0xFF44DDDD ) ;
2017-10-18 20:29:59 +00:00
2017-10-21 12:15:33 +00:00
auto vit = tmpvec ;
2017-10-19 17:09:02 +00:00
while ( vit ! = dst )
2017-10-18 20:29:59 +00:00
{
2017-10-19 17:09:02 +00:00
auto vrange = std : : upper_bound ( vit , dst , * vit + 3.0 / ( revrange * PlotHeight ) , [ ] ( const auto & l , const auto & r ) { return l < r ; } ) ;
2017-10-18 20:29:59 +00:00
assert ( vrange > vit ) ;
if ( std : : distance ( vit , vrange ) = = 1 )
{
2017-10-19 16:28:11 +00:00
DrawPlotPoint ( wpos , x1 , PlotHeight - ( * vit - min ) * revrange * PlotHeight , offset , 0xFF44DDDD , hover , false , * vit , 0 , false ) ;
2017-10-18 20:29:59 +00:00
}
else
{
2017-10-19 16:28:11 +00:00
DrawPlotPoint ( wpos , x1 , PlotHeight - ( * vit - min ) * revrange * PlotHeight , offset , 0xFF44DDDD , hover , false , * vit , 0 , true ) ;
2017-10-18 20:29:59 +00:00
}
vit = vrange ;
}
prevy = it - 1 ;
}
2017-10-13 13:41:20 +00:00
}
2017-10-13 12:54:32 +00:00
2017-11-26 01:31:48 +00:00
char tmp [ 64 ] ;
sprintf ( tmp , " %s " , RealToString ( max , true ) ) ;
DrawTextContrast ( draw , wpos + ImVec2 ( 0 , offset ) , 0x8844DDDD , tmp ) ;
2017-10-13 13:41:20 +00:00
offset + = PlotHeight - ty ;
2017-11-26 01:31:48 +00:00
sprintf ( tmp , " %s " , RealToString ( min , true ) ) ;
DrawTextContrast ( draw , wpos + ImVec2 ( 0 , offset ) , 0x8844DDDD , tmp ) ;
2017-10-13 13:41:20 +00:00
draw - > AddLine ( wpos + ImVec2 ( 0 , offset + ty - 1 ) , wpos + ImVec2 ( w , offset + ty - 1 ) , 0x8844DDDD ) ;
offset + = ty ;
2017-10-13 12:54:32 +00:00
}
2017-10-13 13:41:20 +00:00
offset + = 0.2 * ty ;
2017-10-13 12:54:32 +00:00
}
return offset ;
}
2017-10-18 20:29:59 +00:00
void View : : DrawPlotPoint ( const ImVec2 & wpos , float x , float y , int offset , uint32_t color , bool hover , bool hasPrev , double val , double prev , bool merged )
2017-10-13 13:09:01 +00:00
{
auto draw = ImGui : : GetWindowDrawList ( ) ;
2017-10-18 20:29:59 +00:00
if ( merged )
{
draw - > AddRectFilled ( wpos + ImVec2 ( x - 1.5f , offset + y - 1.5f ) , wpos + ImVec2 ( x + 2.5f , offset + y + 2.5f ) , color ) ;
}
else
{
draw - > AddRect ( wpos + ImVec2 ( x - 1.5f , offset + y - 1.5f ) , wpos + ImVec2 ( x + 2.5f , offset + y + 2.5f ) , color ) ;
}
2017-10-13 13:15:57 +00:00
2017-10-21 11:47:32 +00:00
if ( hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( x - 2 , offset ) , wpos + ImVec2 ( x + 2 , offset + PlotHeight ) ) )
2017-10-13 13:15:57 +00:00
{
ImGui : : BeginTooltip ( ) ;
2017-10-18 18:33:49 +00:00
ImGui : : Text ( " Value: %s " , RealToString ( val , true ) ) ;
2017-10-13 13:15:57 +00:00
if ( hasPrev )
{
2017-10-18 18:33:49 +00:00
ImGui : : Text ( " Change: %s " , RealToString ( val - prev , true ) ) ;
2017-10-13 13:15:57 +00:00
}
ImGui : : EndTooltip ( ) ;
}
2017-10-13 13:09:01 +00:00
}
2017-11-12 00:25:44 +00:00
void View : : DrawInfoWindow ( )
2017-09-29 19:49:14 +00:00
{
2017-11-12 00:25:44 +00:00
if ( m_zoneInfoWindow )
{
DrawZoneInfoWindow ( ) ;
}
else if ( m_gpuInfoWindow )
{
DrawGpuInfoWindow ( ) ;
}
}
2017-09-29 20:06:31 +00:00
2017-11-12 00:25:44 +00:00
void View : : DrawZoneInfoWindow ( )
{
2017-09-29 19:49:14 +00:00
auto & ev = * m_zoneInfoWindow ;
2017-09-29 20:06:31 +00:00
int dmul = 1 ;
2017-09-29 19:49:14 +00:00
bool show = true ;
2018-01-13 12:56:02 +00:00
ImGui : : Begin ( " Zone info " , & show ) ;
2017-09-29 20:13:22 +00:00
2017-09-29 20:01:30 +00:00
if ( ImGui : : Button ( " Zoom to zone " ) )
{
ZoomToZone ( ev ) ;
}
2017-09-30 11:41:03 +00:00
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " Go to parent " ) )
{
2017-10-22 14:15:27 +00:00
auto parent = GetZoneParent ( ev ) ;
if ( parent )
2017-09-30 11:41:03 +00:00
{
2017-10-22 14:15:27 +00:00
m_zoneInfoWindow = parent ;
2017-09-30 11:41:03 +00:00
}
}
2017-09-29 20:06:31 +00:00
ImGui : : Separator ( ) ;
2018-03-19 01:22:08 +00:00
const auto tid = GetZoneThread ( ev ) ;
2018-02-13 13:57:47 +00:00
const auto & srcloc = m_worker . GetSourceLocation ( ev . srcloc ) ;
2017-11-14 22:31:24 +00:00
if ( srcloc . name . active )
2017-09-29 19:49:14 +00:00
{
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " Zone name: %s " , m_worker . GetString ( srcloc . name ) ) ;
2017-09-29 19:49:14 +00:00
}
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " Function: %s " , m_worker . GetString ( srcloc . function ) ) ;
ImGui : : Text ( " Location: %s:%i " , m_worker . GetString ( srcloc . file ) , srcloc . line ) ;
2018-03-19 01:22:08 +00:00
ImGui : : Text ( " Thread: %s " , m_worker . GetThreadString ( tid ) ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (id) " ) ;
if ( ImGui : : IsItemHovered ( ) )
{
ImGui : : BeginTooltip ( ) ;
ImGui : : Text ( " 0x% " PRIX64 , tid ) ;
ImGui : : EndTooltip ( ) ;
}
2017-11-14 22:31:24 +00:00
if ( ev . text . active )
2017-09-29 19:49:14 +00:00
{
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " User text: %s " , m_worker . GetString ( ev . text ) ) ;
2017-09-29 20:06:31 +00:00
dmul + + ;
2017-09-29 19:49:14 +00:00
}
2017-09-29 20:06:31 +00:00
ImGui : : Separator ( ) ;
2018-02-13 13:57:47 +00:00
const auto end = m_worker . GetZoneEnd ( ev ) ;
2017-09-29 20:13:22 +00:00
const auto ztime = end - ev . start ;
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " Time from start of program: %s " , TimeToString ( ev . start - m_worker . GetFrameBegin ( 0 ) ) ) ;
2017-09-29 20:13:22 +00:00
ImGui : : Text ( " Execution time: %s " , TimeToString ( ztime ) ) ;
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " Without profiling: %s " , TimeToString ( ztime - m_worker . GetDelay ( ) * dmul ) ) ;
2017-09-29 20:13:22 +00:00
2018-03-27 23:47:28 +00:00
ImGui : : Separator ( ) ;
std : : vector < const ZoneEvent * > zoneTrace ;
auto parent = GetZoneParent ( ev ) ;
while ( parent )
{
zoneTrace . emplace_back ( parent ) ;
parent = GetZoneParent ( * parent ) ;
}
if ( ! zoneTrace . empty ( ) )
{
bool expand = ImGui : : TreeNode ( " Zone trace " ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%s) " , RealToString ( zoneTrace . size ( ) , true ) ) ;
if ( expand )
{
2018-03-27 23:57:53 +00:00
int idx = 0 ;
2018-03-27 23:47:28 +00:00
for ( auto & v : zoneTrace )
{
const auto & srcloc = m_worker . GetSourceLocation ( v - > srcloc ) ;
const auto txt = srcloc . name . active ? m_worker . GetString ( srcloc . name ) : m_worker . GetString ( srcloc . function ) ;
2018-03-27 23:57:53 +00:00
ImGui : : PushID ( idx + + ) ;
2018-03-27 23:53:59 +00:00
auto sel = ImGui : : Selectable ( txt , false ) ;
auto hover = ImGui : : IsItemHovered ( ) ;
2018-03-27 23:47:28 +00:00
ImGui : : SameLine ( ) ;
2018-03-28 17:35:33 +00:00
ImGui : : TextDisabled ( " (%s) %s:%i " , TimeToString ( m_worker . GetZoneEnd ( * v ) - v - > start ) , m_worker . GetString ( srcloc . file ) , srcloc . line ) ;
2018-03-27 23:57:53 +00:00
ImGui : : PopID ( ) ;
2018-03-27 23:53:59 +00:00
if ( sel )
{
m_zoneInfoWindow = v ;
}
if ( hover )
{
m_zoneHighlight = v ;
if ( ImGui : : IsMouseClicked ( 2 ) )
{
ZoomToZone ( * v ) ;
}
ZoneTooltip ( * v ) ;
}
2018-03-27 23:47:28 +00:00
}
ImGui : : TreePop ( ) ;
}
}
2017-09-29 20:32:03 +00:00
auto ctt = std : : make_unique < uint64_t [ ] > ( ev . child . size ( ) ) ;
auto cti = std : : make_unique < uint32_t [ ] > ( ev . child . size ( ) ) ;
2017-09-29 20:13:22 +00:00
uint64_t ctime = 0 ;
2017-10-28 19:50:06 +00:00
for ( size_t i = 0 ; i < ev . child . size ( ) ; i + + )
2017-09-29 20:13:22 +00:00
{
2018-02-13 13:57:47 +00:00
const auto cend = m_worker . GetZoneEnd ( * ev . child [ i ] ) ;
2017-09-29 20:32:03 +00:00
const auto ct = cend - ev . child [ i ] - > start ;
ctime + = ct ;
ctt [ i ] = ct ;
2017-10-28 19:50:06 +00:00
cti [ i ] = uint32_t ( i ) ;
2017-09-29 20:13:22 +00:00
}
2017-09-29 20:32:03 +00:00
std : : sort ( cti . get ( ) , cti . get ( ) + ev . child . size ( ) , [ & ctt ] ( const auto & lhs , const auto & rhs ) { return ctt [ lhs ] > ctt [ rhs ] ; } ) ;
if ( ! ev . child . empty ( ) )
{
2018-03-27 23:47:20 +00:00
bool expand = ImGui : : TreeNode ( " Child zones " ) ;
2018-03-27 23:34:12 +00:00
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%s) " , RealToString ( ev . child . size ( ) , true ) ) ;
if ( expand )
2017-09-29 20:32:03 +00:00
{
2018-03-27 23:34:12 +00:00
const auto ty = ImGui : : GetTextLineHeight ( ) ;
ImGui : : Columns ( 2 ) ;
2018-03-27 23:47:08 +00:00
ImGui : : TextColored ( ImVec4 ( 1.0f , 1.0f , 0.4f , 1.0f ) , " Self time " ) ;
2018-03-27 23:34:12 +00:00
ImGui : : NextColumn ( ) ;
char buf [ 128 ] ;
sprintf ( buf , " %s (%.2f%%) " , TimeToString ( ztime - ctime ) , double ( ztime - ctime ) / ztime * 100 ) ;
ImGui : : ProgressBar ( double ( ztime - ctime ) / ztime , ImVec2 ( - 1 , ty ) , buf ) ;
ImGui : : NextColumn ( ) ;
for ( size_t i = 0 ; i < ev . child . size ( ) ; i + + )
2017-09-29 20:38:38 +00:00
{
2018-03-27 23:34:12 +00:00
auto & cev = * ev . child [ cti [ i ] ] ;
const auto & csl = m_worker . GetSourceLocation ( cev . srcloc ) ;
const auto txt = csl . name . active ? m_worker . GetString ( csl . name ) : m_worker . GetString ( csl . function ) ;
bool b = false ;
2018-03-27 23:57:53 +00:00
ImGui : : PushID ( ( int ) i ) ;
2018-03-27 23:34:12 +00:00
if ( ImGui : : Selectable ( txt , & b , ImGuiSelectableFlags_SpanAllColumns ) )
2017-09-29 20:38:38 +00:00
{
2018-03-27 23:34:12 +00:00
m_zoneInfoWindow = & cev ;
2017-09-29 20:38:38 +00:00
}
2018-03-27 23:34:12 +00:00
if ( ImGui : : IsItemHovered ( ) )
{
m_zoneHighlight = & cev ;
if ( ImGui : : IsMouseClicked ( 2 ) )
{
ZoomToZone ( cev ) ;
}
ZoneTooltip ( cev ) ;
}
2018-03-27 23:57:53 +00:00
ImGui : : PopID ( ) ;
2018-03-27 23:34:12 +00:00
ImGui : : NextColumn ( ) ;
const auto part = double ( ctt [ cti [ i ] ] ) / ztime ;
char buf [ 128 ] ;
sprintf ( buf , " %s (%.2f%%) " , TimeToString ( ctt [ cti [ i ] ] ) , part * 100 ) ;
ImGui : : ProgressBar ( part , ImVec2 ( - 1 , ty ) , buf ) ;
ImGui : : NextColumn ( ) ;
2017-09-29 20:38:38 +00:00
}
2018-03-27 23:34:12 +00:00
ImGui : : EndColumns ( ) ;
ImGui : : TreePop ( ) ;
2017-09-29 20:32:03 +00:00
}
}
2017-09-29 19:49:14 +00:00
ImGui : : End ( ) ;
2017-09-29 20:06:31 +00:00
2017-09-29 19:49:14 +00:00
if ( ! show ) m_zoneInfoWindow = nullptr ;
}
2017-11-12 00:25:44 +00:00
void View : : DrawGpuInfoWindow ( )
{
auto & ev = * m_gpuInfoWindow ;
bool show = true ;
2018-01-13 12:56:02 +00:00
ImGui : : Begin ( " Zone info " , & show ) ;
2017-11-12 00:25:44 +00:00
if ( ImGui : : Button ( " Zoom to zone " ) )
{
ZoomToZone ( ev ) ;
}
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " Go to parent " ) )
{
auto parent = GetZoneParent ( ev ) ;
if ( parent )
{
m_gpuInfoWindow = parent ;
}
}
ImGui : : Separator ( ) ;
2018-03-19 15:11:44 +00:00
const auto tid = GetZoneThread ( ev ) ;
2018-02-13 13:57:47 +00:00
const auto & srcloc = m_worker . GetSourceLocation ( ev . srcloc ) ;
ImGui : : Text ( " Zone name: %s " , m_worker . GetString ( srcloc . name ) ) ;
ImGui : : Text ( " Function: %s " , m_worker . GetString ( srcloc . function ) ) ;
ImGui : : Text ( " Location: %s:%i " , m_worker . GetString ( srcloc . file ) , srcloc . line ) ;
2018-03-19 15:11:44 +00:00
ImGui : : Text ( " Thread: %s " , m_worker . GetThreadString ( tid ) ) ;
2018-03-19 01:22:08 +00:00
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (id) " ) ;
if ( ImGui : : IsItemHovered ( ) )
{
ImGui : : BeginTooltip ( ) ;
2018-03-19 15:11:44 +00:00
ImGui : : Text ( " 0x% " PRIX64 , tid ) ;
2018-03-19 01:22:08 +00:00
ImGui : : EndTooltip ( ) ;
}
2017-11-12 00:25:44 +00:00
ImGui : : Separator ( ) ;
2018-02-13 13:57:47 +00:00
const auto end = m_worker . GetZoneEnd ( ev ) ;
2017-11-12 00:25:44 +00:00
const auto ztime = end - ev . gpuStart ;
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " Time from start of program: %s " , TimeToString ( ev . gpuStart - m_worker . GetFrameBegin ( 0 ) ) ) ;
2017-11-12 00:25:44 +00:00
ImGui : : Text ( " GPU execution time: %s " , TimeToString ( ztime ) ) ;
ImGui : : Text ( " CPU command setup time: %s " , TimeToString ( ev . cpuEnd - ev . cpuStart ) ) ;
ImGui : : Text ( " Delay to execution: %s " , TimeToString ( ev . gpuStart - ev . cpuStart ) ) ;
2018-03-27 23:47:28 +00:00
ImGui : : Separator ( ) ;
std : : vector < const GpuEvent * > zoneTrace ;
auto parent = GetZoneParent ( ev ) ;
while ( parent )
{
zoneTrace . emplace_back ( parent ) ;
parent = GetZoneParent ( * parent ) ;
}
if ( ! zoneTrace . empty ( ) )
{
bool expand = ImGui : : TreeNode ( " Zone trace " ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%s) " , RealToString ( zoneTrace . size ( ) , true ) ) ;
if ( expand )
{
2018-03-27 23:57:53 +00:00
int idx = 0 ;
2018-03-27 23:47:28 +00:00
for ( auto & v : zoneTrace )
{
const auto & srcloc = m_worker . GetSourceLocation ( v - > srcloc ) ;
const auto txt = srcloc . name . active ? m_worker . GetString ( srcloc . name ) : m_worker . GetString ( srcloc . function ) ;
2018-03-27 23:57:53 +00:00
ImGui : : PushID ( idx + + ) ;
2018-03-27 23:53:59 +00:00
auto sel = ImGui : : Selectable ( txt , false ) ;
auto hover = ImGui : : IsItemHovered ( ) ;
2018-03-27 23:47:28 +00:00
ImGui : : SameLine ( ) ;
2018-03-28 17:35:33 +00:00
ImGui : : TextDisabled ( " (%s) %s:%i " , TimeToString ( m_worker . GetZoneEnd ( * v ) - v - > gpuStart ) , m_worker . GetString ( srcloc . file ) , srcloc . line ) ;
2018-03-27 23:57:53 +00:00
ImGui : : PopID ( ) ;
2018-03-27 23:53:59 +00:00
if ( sel )
{
m_gpuInfoWindow = v ;
}
if ( hover )
{
m_gpuHighlight = v ;
if ( ImGui : : IsMouseClicked ( 2 ) )
{
ZoomToZone ( * v ) ;
}
ZoneTooltip ( * v ) ;
}
2018-03-27 23:47:28 +00:00
}
ImGui : : TreePop ( ) ;
}
}
2017-11-12 00:25:44 +00:00
auto ctt = std : : make_unique < uint64_t [ ] > ( ev . child . size ( ) ) ;
auto cti = std : : make_unique < uint32_t [ ] > ( ev . child . size ( ) ) ;
uint64_t ctime = 0 ;
for ( size_t i = 0 ; i < ev . child . size ( ) ; i + + )
{
2018-02-13 13:57:47 +00:00
const auto cend = m_worker . GetZoneEnd ( * ev . child [ i ] ) ;
2017-11-12 00:25:44 +00:00
const auto ct = cend - ev . child [ i ] - > gpuStart ;
ctime + = ct ;
ctt [ i ] = ct ;
cti [ i ] = uint32_t ( i ) ;
}
std : : sort ( cti . get ( ) , cti . get ( ) + ev . child . size ( ) , [ & ctt ] ( const auto & lhs , const auto & rhs ) { return ctt [ lhs ] > ctt [ rhs ] ; } ) ;
if ( ! ev . child . empty ( ) )
{
2018-03-27 23:47:20 +00:00
bool expand = ImGui : : TreeNode ( " Child zones " ) ;
2018-03-27 23:34:12 +00:00
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%s) " , RealToString ( ev . child . size ( ) , true ) ) ;
if ( expand )
2017-11-12 00:25:44 +00:00
{
2018-03-27 23:34:12 +00:00
const auto ty = ImGui : : GetTextLineHeight ( ) ;
ImGui : : Columns ( 2 ) ;
2018-03-27 23:47:08 +00:00
ImGui : : TextColored ( ImVec4 ( 1.0f , 1.0f , 0.4f , 1.0f ) , " Self time " ) ;
2018-03-27 23:34:12 +00:00
ImGui : : NextColumn ( ) ;
char buf [ 128 ] ;
sprintf ( buf , " %s (%.2f%%) " , TimeToString ( ztime - ctime ) , double ( ztime - ctime ) / ztime * 100 ) ;
ImGui : : ProgressBar ( double ( ztime - ctime ) / ztime , ImVec2 ( - 1 , ty ) , buf ) ;
ImGui : : NextColumn ( ) ;
for ( size_t i = 0 ; i < ev . child . size ( ) ; i + + )
2017-11-12 00:25:44 +00:00
{
2018-03-27 23:34:12 +00:00
auto & cev = * ev . child [ cti [ i ] ] ;
const auto & csl = m_worker . GetSourceLocation ( cev . srcloc ) ;
bool b = false ;
2018-03-27 23:57:53 +00:00
ImGui : : PushID ( ( int ) i ) ;
2018-03-27 23:34:12 +00:00
if ( ImGui : : Selectable ( m_worker . GetString ( csl . name ) , & b , ImGuiSelectableFlags_SpanAllColumns ) )
2017-11-12 00:25:44 +00:00
{
2018-03-27 23:34:12 +00:00
m_gpuInfoWindow = & cev ;
2017-11-12 00:25:44 +00:00
}
2018-03-27 23:34:12 +00:00
if ( ImGui : : IsItemHovered ( ) )
{
m_gpuHighlight = & cev ;
if ( ImGui : : IsMouseClicked ( 2 ) )
{
ZoomToZone ( cev ) ;
}
ZoneTooltip ( cev ) ;
}
2018-03-27 23:57:53 +00:00
ImGui : : PopID ( ) ;
2018-03-27 23:34:12 +00:00
ImGui : : NextColumn ( ) ;
const auto part = double ( ctt [ cti [ i ] ] ) / ztime ;
char buf [ 128 ] ;
sprintf ( buf , " %s (%.2f%%) " , TimeToString ( ctt [ cti [ i ] ] ) , part * 100 ) ;
ImGui : : ProgressBar ( part , ImVec2 ( - 1 , ty ) , buf ) ;
ImGui : : NextColumn ( ) ;
2017-11-12 00:25:44 +00:00
}
2018-03-27 23:34:12 +00:00
ImGui : : EndColumns ( ) ;
ImGui : : TreePop ( ) ;
2017-11-12 00:25:44 +00:00
}
}
ImGui : : End ( ) ;
if ( ! show ) m_gpuInfoWindow = nullptr ;
}
2017-10-13 11:32:23 +00:00
void View : : DrawOptions ( )
{
2017-10-22 11:13:26 +00:00
const auto tw = ImGui : : GetFontSize ( ) ;
2018-01-13 12:56:02 +00:00
ImGui : : Begin ( " Options " , & m_showOptions , ImGuiWindowFlags_AlwaysAutoResize ) ;
2018-03-15 22:33:05 +00:00
auto sz = m_worker . GetGpuData ( ) . size ( ) ;
if ( sz > 0 )
2017-11-30 14:34:52 +00:00
{
2018-03-15 22:33:05 +00:00
ImGui : : Checkbox ( " Draw GPU zones " , & m_drawGpuZones ) ;
const auto expand = ImGui : : TreeNode ( " GPU zones " ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%zu) " , sz ) ;
if ( expand )
{
for ( size_t i = 0 ; i < sz ; i + + )
{
char buf [ 1024 ] ;
sprintf ( buf , " GPU context %zu " , i ) ;
ImGui : : Checkbox ( buf , & Visible ( m_worker . GetGpuData ( ) [ i ] ) ) ;
}
ImGui : : TreePop ( ) ;
}
2017-11-30 14:34:52 +00:00
}
2018-03-15 22:33:05 +00:00
2017-11-11 21:56:05 +00:00
ImGui : : Checkbox ( " Draw CPU zones " , & m_drawZones ) ;
2017-10-22 11:56:05 +00:00
int ns = ( int ) m_namespace ;
2017-10-22 13:27:07 +00:00
ImGui : : Combo ( " Namespaces " , & ns , " Full \0 Shortened \0 None \0 " ) ;
2017-10-22 11:56:05 +00:00
m_namespace = ( Namespace ) ns ;
2018-03-15 22:33:05 +00:00
if ( ! m_worker . GetLockMap ( ) . empty ( ) )
2017-10-22 11:25:58 +00:00
{
2018-03-15 22:33:05 +00:00
ImGui : : Separator ( ) ;
ImGui : : Checkbox ( " Draw locks " , & m_drawLocks ) ;
ImGui : : SameLine ( ) ;
ImGui : : Checkbox ( " Only contended " , & m_onlyContendedLocks ) ;
const auto expand = ImGui : : TreeNode ( " Locks " ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%zu) " , m_worker . GetLockMap ( ) . size ( ) ) ;
if ( ImGui : : IsItemHovered ( ) )
2017-12-10 20:37:39 +00:00
{
2018-03-15 22:33:05 +00:00
ImGui : : BeginTooltip ( ) ;
ImGui : : Text ( " Locks with no recorded events are counted, but not listed. " ) ;
ImGui : : EndTooltip ( ) ;
}
if ( expand )
{
for ( const auto & l : m_worker . GetLockMap ( ) )
{
if ( l . second . valid )
{
char buf [ 1024 ] ;
sprintf ( buf , " % " PRIu32 " : %s " , l . first , m_worker . GetString ( m_worker . GetSourceLocation ( l . second . srcloc ) . function ) ) ;
ImGui : : Checkbox ( buf , & Visible ( & l . second ) ) ;
}
}
ImGui : : TreePop ( ) ;
2017-12-10 20:37:39 +00:00
}
2017-10-22 11:25:58 +00:00
}
2018-03-15 22:33:05 +00:00
if ( ! m_worker . GetPlots ( ) . empty ( ) )
2017-10-22 11:17:34 +00:00
{
2018-03-15 22:33:05 +00:00
ImGui : : Separator ( ) ;
ImGui : : Checkbox ( " Draw plots " , & m_drawPlots ) ;
const auto expand = ImGui : : TreeNode ( " Plots " ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%zu) " , m_worker . GetPlots ( ) . size ( ) ) ;
if ( expand )
{
for ( const auto & p : m_worker . GetPlots ( ) )
{
ImGui : : Checkbox ( m_worker . GetString ( p - > name ) , & Visible ( p ) ) ;
}
ImGui : : TreePop ( ) ;
}
2017-10-22 11:17:34 +00:00
}
2018-03-15 22:33:05 +00:00
2017-10-22 11:13:26 +00:00
ImGui : : Separator ( ) ;
2018-03-15 22:33:05 +00:00
const auto expand = ImGui : : TreeNode ( " Visible threads: " ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%zu) " , m_worker . GetThreadData ( ) . size ( ) ) ;
if ( expand )
2017-10-22 11:13:26 +00:00
{
2018-03-15 22:33:05 +00:00
int idx = 0 ;
for ( const auto & t : m_worker . GetThreadData ( ) )
{
ImGui : : PushID ( idx + + ) ;
ImGui : : Checkbox ( m_worker . GetThreadString ( t - > id ) , & Visible ( t ) ) ;
ImGui : : PopID ( ) ;
}
ImGui : : TreePop ( ) ;
2017-10-22 11:13:26 +00:00
}
2017-10-13 11:32:23 +00:00
ImGui : : End ( ) ;
}
2017-10-14 12:36:30 +00:00
void View : : DrawMessages ( )
{
2018-01-13 12:56:02 +00:00
ImGui : : Begin ( " Messages " , & m_showMessages ) ;
2018-02-13 13:57:47 +00:00
for ( const auto & v : m_worker . GetMessages ( ) )
2017-10-14 12:36:30 +00:00
{
2017-10-16 23:20:10 +00:00
char tmp [ 64 * 1024 ] ;
2018-02-13 13:57:47 +00:00
sprintf ( tmp , " %10s | %s " , TimeToString ( v - > time - m_worker . GetFrameBegin ( 0 ) ) , m_worker . GetString ( v - > ref ) ) ;
2017-10-14 13:47:06 +00:00
if ( m_msgHighlight = = v )
{
ImGui : : TextColored ( ImVec4 ( 0xDD / 255.f , 0x22 / 255.f , 0x22 / 255.f , 1.f ) , " %s " , tmp ) ;
}
else
{
ImGui : : Text ( " %s " , tmp ) ;
}
2017-10-14 12:36:30 +00:00
if ( ImGui : : IsItemClicked ( ) )
{
m_pause = true ;
2017-10-14 16:34:18 +00:00
const auto hr = std : : max < uint64_t > ( 1 , ( m_zvEnd - m_zvStart ) / 2 ) ;
2017-11-27 21:12:26 +00:00
ZoomToRange ( v - > time - hr , v - > time + hr ) ;
2017-10-14 12:36:30 +00:00
}
}
ImGui : : End ( ) ;
}
2018-01-17 11:49:50 +00:00
void View : : DrawFindZone ( )
{
ImGui : : Begin ( " Find Zone " , & m_findZone . show ) ;
2018-03-18 11:55:54 +00:00
# ifdef TRACY_NO_STATISTICS
ImGui : : TextWrapped ( " Collection of statistical data is disabled in this build. " ) ;
ImGui : : TextWrapped ( " Rebuild without the TRACY_NO_STATISTICS macro to enable zone search. " ) ;
# else
2018-01-17 11:49:50 +00:00
ImGui : : InputText ( " " , m_findZone . pattern , 1024 ) ;
ImGui : : SameLine ( ) ;
2018-02-15 15:24:01 +00:00
const bool findClicked = ImGui : : Button ( " Find " ) ;
2018-01-17 11:49:50 +00:00
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " Clear " ) )
{
2018-03-04 21:52:36 +00:00
m_findZone . Reset ( ) ;
2018-01-17 11:49:50 +00:00
}
2018-02-15 15:24:01 +00:00
if ( findClicked )
2018-01-17 11:49:50 +00:00
{
2018-03-04 21:52:36 +00:00
m_findZone . Reset ( ) ;
2018-01-17 11:49:50 +00:00
FindZones ( ) ;
}
2018-03-04 20:10:10 +00:00
if ( ! m_findZone . match . empty ( ) )
{
ImGui : : Separator ( ) ;
2018-03-24 01:45:24 +00:00
bool expand = ImGui : : TreeNodeEx ( " Matched source locations " , ImGuiTreeNodeFlags_DefaultOpen ) ;
2018-03-20 19:18:23 +00:00
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (%zu) " , m_findZone . match . size ( ) ) ;
if ( expand )
2018-03-04 20:10:10 +00:00
{
2018-03-18 15:41:58 +00:00
auto prev = m_findZone . selMatch ;
2018-03-04 21:11:50 +00:00
int idx = 0 ;
for ( auto & v : m_findZone . match )
2018-03-04 20:10:10 +00:00
{
2018-03-18 15:07:07 +00:00
auto & srcloc = m_worker . GetSourceLocation ( v ) ;
2018-03-18 19:20:24 +00:00
auto & zones = m_worker . GetZonesForSourceLocation ( v ) . zones ;
2018-03-18 15:07:07 +00:00
ImGui : : PushID ( idx ) ;
ImGui : : RadioButton ( m_worker . GetString ( srcloc . name . active ? srcloc . name : srcloc . function ) , & m_findZone . selMatch , idx + + ) ;
2018-03-04 20:10:10 +00:00
ImGui : : SameLine ( ) ;
2018-03-18 15:11:08 +00:00
ImGui : : TextColored ( ImVec4 ( 0.5 , 0.5 , 0.5 , 1 ) , " (%s) %s:%i " , RealToString ( zones . size ( ) , true ) , m_worker . GetString ( srcloc . file ) , srcloc . line ) ;
2018-03-04 20:10:10 +00:00
ImGui : : PopID ( ) ;
}
ImGui : : TreePop ( ) ;
2018-03-18 15:41:58 +00:00
if ( m_findZone . selMatch ! = prev )
{
m_findZone . ResetThreads ( ) ;
}
2018-03-04 20:10:10 +00:00
}
2018-02-15 16:25:16 +00:00
ImGui : : Separator ( ) ;
2018-02-15 15:17:16 +00:00
2018-03-24 01:45:24 +00:00
if ( ImGui : : TreeNodeEx ( " Histogram " , ImGuiTreeNodeFlags_DefaultOpen ) )
2018-01-17 11:49:50 +00:00
{
2018-02-20 15:01:33 +00:00
const auto ty = ImGui : : GetFontSize ( ) ;
2018-03-18 19:20:24 +00:00
auto & zoneData = m_worker . GetZonesForSourceLocation ( m_findZone . match [ m_findZone . selMatch ] ) ;
auto & zones = zoneData . zones ;
auto tmin = zoneData . min ;
auto tmax = zoneData . max ;
2018-02-15 16:25:16 +00:00
2018-03-18 01:43:17 +00:00
if ( tmin ! = std : : numeric_limits < int64_t > : : max ( ) )
2018-03-05 19:15:18 +00:00
{
2018-03-18 01:43:17 +00:00
ImGui : : Checkbox ( " Log values " , & m_findZone . logVal ) ;
ImGui : : SameLine ( ) ;
ImGui : : Checkbox ( " Log time " , & m_findZone . logTime ) ;
ImGui : : SameLine ( ) ;
ImGui : : Checkbox ( " Cumulate time " , & m_findZone . cumulateTime ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (?) " ) ;
if ( ImGui : : IsItemHovered ( ) )
{
ImGui : : BeginTooltip ( ) ;
ImGui : : Text ( " Show total time taken by calls in each bin instead of call counts. " ) ;
ImGui : : EndTooltip ( ) ;
}
2018-02-16 12:28:40 +00:00
2018-03-18 01:43:17 +00:00
ImGui : : Text ( " Time range: %s - %s (%s) " , TimeToString ( tmin ) , TimeToString ( tmax ) , TimeToString ( tmax - tmin ) ) ;
2018-01-17 11:49:50 +00:00
2018-03-18 01:43:17 +00:00
const auto dt = double ( tmax - tmin ) ;
2018-03-20 15:28:55 +00:00
const auto selThread = m_findZone . selThread ;
const auto showThreads = m_findZone . showThreads ;
const auto cumulateTime = m_findZone . cumulateTime ;
2018-02-15 16:25:16 +00:00
2018-03-18 01:43:17 +00:00
if ( dt > 0 )
2018-02-16 12:09:24 +00:00
{
2018-03-18 01:43:17 +00:00
const auto w = ImGui : : GetContentRegionAvail ( ) . x ;
2018-02-16 13:42:16 +00:00
2018-03-18 01:43:17 +00:00
const auto numBins = int64_t ( w - 4 ) ;
if ( numBins > 1 )
2018-02-15 16:25:16 +00:00
{
2018-03-18 01:43:17 +00:00
auto bins = std : : make_unique < int64_t [ ] > ( numBins ) ;
memset ( bins . get ( ) , 0 , sizeof ( int64_t ) * numBins ) ;
2018-03-05 19:23:58 +00:00
2018-03-18 01:43:17 +00:00
auto binTime = std : : make_unique < int64_t [ ] > ( numBins ) ;
memset ( binTime . get ( ) , 0 , sizeof ( int64_t ) * numBins ) ;
2018-03-20 13:37:58 +00:00
auto selBin = std : : make_unique < int64_t [ ] > ( numBins ) ;
memset ( selBin . get ( ) , 0 , sizeof ( int64_t ) * numBins ) ;
2018-03-20 15:56:11 +00:00
int64_t selBinTime = 0 ;
2018-03-18 01:43:17 +00:00
int64_t selectionTime = 0 ;
if ( m_findZone . highlight . active )
2018-02-16 12:09:24 +00:00
{
2018-03-18 01:43:17 +00:00
const auto s = std : : min ( m_findZone . highlight . start , m_findZone . highlight . end ) ;
const auto e = std : : max ( m_findZone . highlight . start , m_findZone . highlight . end ) ;
2018-03-20 15:28:55 +00:00
if ( selThread ! = m_findZone . Unselected )
2018-02-16 14:34:22 +00:00
{
2018-03-20 13:37:58 +00:00
if ( m_findZone . logTime )
2018-03-05 19:23:58 +00:00
{
2018-03-20 13:37:58 +00:00
const auto tMinLog = log10 ( tmin ) ;
const auto idt = numBins / ( log10 ( tmax ) - tMinLog ) ;
for ( auto & ev : zones )
2018-03-18 01:43:17 +00:00
{
2018-03-20 13:37:58 +00:00
const auto timeSpan = m_worker . GetZoneEndDirect ( * ev . zone ) - ev . zone - > start ;
if ( timeSpan ! = 0 )
{
const auto bin = std : : min ( numBins - 1 , int64_t ( ( log10 ( timeSpan ) - tMinLog ) * idt ) ) ;
bins [ bin ] + + ;
binTime [ bin ] + = timeSpan ;
2018-03-20 15:28:55 +00:00
if ( selThread = = ( showThreads ? ev . thread : ( ev . zone - > text . active ? ev . zone - > text . idx : std : : numeric_limits < uint64_t > : : max ( ) ) ) )
2018-03-20 13:37:58 +00:00
{
2018-03-20 15:28:55 +00:00
if ( cumulateTime ) selBin [ bin ] + = timeSpan ; else selBin [ bin ] + + ;
2018-03-20 15:56:11 +00:00
selBinTime + = timeSpan ;
2018-03-20 13:37:58 +00:00
}
if ( timeSpan > = s & & timeSpan < = e ) selectionTime + = timeSpan ;
}
}
}
else
{
const auto idt = numBins / dt ;
for ( auto & ev : zones )
{
const auto timeSpan = m_worker . GetZoneEndDirect ( * ev . zone ) - ev . zone - > start ;
if ( timeSpan ! = 0 )
{
const auto bin = std : : min ( numBins - 1 , int64_t ( ( timeSpan - tmin ) * idt ) ) ;
bins [ bin ] + + ;
binTime [ bin ] + = timeSpan ;
2018-03-20 15:28:55 +00:00
if ( selThread = = ( showThreads ? ev . thread : ( ev . zone - > text . active ? ev . zone - > text . idx : std : : numeric_limits < uint64_t > : : max ( ) ) ) )
2018-03-20 13:37:58 +00:00
{
2018-03-20 15:28:55 +00:00
if ( cumulateTime ) selBin [ bin ] + = timeSpan ; else selBin [ bin ] + + ;
2018-03-20 15:56:11 +00:00
selBinTime + = timeSpan ;
2018-03-20 13:37:58 +00:00
}
if ( timeSpan > = s & & timeSpan < = e ) selectionTime + = timeSpan ;
}
2018-03-18 01:43:17 +00:00
}
2018-03-05 19:23:58 +00:00
}
}
2018-03-18 01:43:17 +00:00
else
2018-03-05 19:23:58 +00:00
{
2018-03-20 13:37:58 +00:00
if ( m_findZone . logTime )
{
const auto tMinLog = log10 ( tmin ) ;
const auto idt = numBins / ( log10 ( tmax ) - tMinLog ) ;
for ( auto & ev : zones )
{
const auto timeSpan = m_worker . GetZoneEndDirect ( * ev . zone ) - ev . zone - > start ;
if ( timeSpan ! = 0 )
{
const auto bin = std : : min ( numBins - 1 , int64_t ( ( log10 ( timeSpan ) - tMinLog ) * idt ) ) ;
bins [ bin ] + + ;
binTime [ bin ] + = timeSpan ;
if ( timeSpan > = s & & timeSpan < = e ) selectionTime + = timeSpan ;
}
}
}
else
2018-03-05 19:23:58 +00:00
{
2018-03-20 13:37:58 +00:00
const auto idt = numBins / dt ;
for ( auto & ev : zones )
2018-03-18 01:43:17 +00:00
{
2018-03-20 13:37:58 +00:00
const auto timeSpan = m_worker . GetZoneEndDirect ( * ev . zone ) - ev . zone - > start ;
if ( timeSpan ! = 0 )
{
const auto bin = std : : min ( numBins - 1 , int64_t ( ( timeSpan - tmin ) * idt ) ) ;
bins [ bin ] + + ;
binTime [ bin ] + = timeSpan ;
if ( timeSpan > = s & & timeSpan < = e ) selectionTime + = timeSpan ;
}
2018-03-18 01:43:17 +00:00
}
2018-03-05 19:23:58 +00:00
}
2018-02-16 14:34:22 +00:00
}
}
2018-03-18 01:43:17 +00:00
else
2018-02-16 14:34:22 +00:00
{
2018-03-20 15:28:55 +00:00
if ( selThread ! = m_findZone . Unselected )
2018-02-16 14:34:22 +00:00
{
2018-03-20 13:37:58 +00:00
if ( m_findZone . logTime )
{
const auto tMinLog = log10 ( tmin ) ;
const auto idt = numBins / ( log10 ( tmax ) - tMinLog ) ;
for ( auto & ev : zones )
{
const auto timeSpan = m_worker . GetZoneEndDirect ( * ev . zone ) - ev . zone - > start ;
if ( timeSpan ! = 0 )
{
const auto bin = std : : min ( numBins - 1 , int64_t ( ( log10 ( timeSpan ) - tMinLog ) * idt ) ) ;
bins [ bin ] + + ;
binTime [ bin ] + = timeSpan ;
2018-03-20 15:28:55 +00:00
if ( selThread = = ( showThreads ? ev . thread : ( ev . zone - > text . active ? ev . zone - > text . idx : std : : numeric_limits < uint64_t > : : max ( ) ) ) )
2018-03-20 13:37:58 +00:00
{
2018-03-20 15:28:55 +00:00
if ( cumulateTime ) selBin [ bin ] + = timeSpan ; else selBin [ bin ] + + ;
2018-03-20 15:56:11 +00:00
selBinTime + = timeSpan ;
2018-03-20 13:37:58 +00:00
}
}
}
}
else
2018-03-05 19:23:58 +00:00
{
2018-03-20 13:37:58 +00:00
const auto idt = numBins / dt ;
for ( auto & ev : zones )
2018-03-18 01:43:17 +00:00
{
2018-03-20 13:37:58 +00:00
const auto timeSpan = m_worker . GetZoneEndDirect ( * ev . zone ) - ev . zone - > start ;
if ( timeSpan ! = 0 )
{
const auto bin = std : : min ( numBins - 1 , int64_t ( ( timeSpan - tmin ) * idt ) ) ;
bins [ bin ] + + ;
binTime [ bin ] + = timeSpan ;
2018-03-20 15:28:55 +00:00
if ( selThread = = ( showThreads ? ev . thread : ( ev . zone - > text . active ? ev . zone - > text . idx : std : : numeric_limits < uint64_t > : : max ( ) ) ) )
2018-03-20 13:37:58 +00:00
{
2018-03-20 15:28:55 +00:00
if ( cumulateTime ) selBin [ bin ] + = timeSpan ; else selBin [ bin ] + + ;
2018-03-20 15:56:11 +00:00
selBinTime + = timeSpan ;
2018-03-20 13:37:58 +00:00
}
}
2018-03-18 01:43:17 +00:00
}
2018-03-05 19:23:58 +00:00
}
}
2018-03-18 01:43:17 +00:00
else
2018-03-05 19:23:58 +00:00
{
2018-03-20 13:37:58 +00:00
if ( m_findZone . logTime )
2018-03-05 19:23:58 +00:00
{
2018-03-20 13:37:58 +00:00
const auto tMinLog = log10 ( tmin ) ;
const auto idt = numBins / ( log10 ( tmax ) - tMinLog ) ;
for ( auto & ev : zones )
2018-03-18 01:43:17 +00:00
{
2018-03-20 13:37:58 +00:00
const auto timeSpan = m_worker . GetZoneEndDirect ( * ev . zone ) - ev . zone - > start ;
if ( timeSpan ! = 0 )
{
const auto bin = std : : min ( numBins - 1 , int64_t ( ( log10 ( timeSpan ) - tMinLog ) * idt ) ) ;
bins [ bin ] + + ;
binTime [ bin ] + = timeSpan ;
}
}
}
else
{
const auto idt = numBins / dt ;
for ( auto & ev : zones )
{
const auto timeSpan = m_worker . GetZoneEndDirect ( * ev . zone ) - ev . zone - > start ;
if ( timeSpan ! = 0 )
{
const auto bin = std : : min ( numBins - 1 , int64_t ( ( timeSpan - tmin ) * idt ) ) ;
bins [ bin ] + + ;
binTime [ bin ] + = timeSpan ;
}
2018-03-18 01:43:17 +00:00
}
2018-03-05 19:23:58 +00:00
}
2018-02-16 14:34:22 +00:00
}
2018-02-16 12:09:24 +00:00
}
2018-01-17 11:49:50 +00:00
2018-03-18 01:43:17 +00:00
int64_t timeTotal = binTime [ 0 ] ;
int64_t maxVal ;
2018-03-20 15:28:55 +00:00
if ( cumulateTime )
2018-03-05 19:15:18 +00:00
{
2018-03-18 01:43:17 +00:00
maxVal = binTime [ 0 ] ;
for ( int i = 1 ; i < numBins ; i + + )
{
maxVal = std : : max ( maxVal , binTime [ i ] ) ;
timeTotal + = binTime [ i ] ;
}
2018-03-05 19:15:18 +00:00
}
2018-03-18 01:43:17 +00:00
else
2018-03-05 19:15:18 +00:00
{
2018-03-18 01:43:17 +00:00
maxVal = bins [ 0 ] ;
for ( int i = 1 ; i < numBins ; i + + )
{
maxVal = std : : max ( maxVal , bins [ i ] ) ;
timeTotal + = binTime [ i ] ;
}
2018-03-05 19:15:18 +00:00
}
2018-02-15 16:25:16 +00:00
2018-03-18 01:43:17 +00:00
ImGui : : Text ( " Total time: %s " , TimeToString ( timeTotal ) ) ;
ImGui : : SameLine ( ) ;
ImGui : : Spacing ( ) ;
ImGui : : SameLine ( ) ;
2018-03-20 15:28:55 +00:00
ImGui : : Text ( " Max counts: %s " , cumulateTime ? TimeToString ( maxVal ) : RealToString ( maxVal , true ) ) ;
2018-02-16 15:19:31 +00:00
2018-03-18 01:43:17 +00:00
if ( m_findZone . highlight . active )
{
const auto s = std : : min ( m_findZone . highlight . start , m_findZone . highlight . end ) ;
const auto e = std : : max ( m_findZone . highlight . start , m_findZone . highlight . end ) ;
ImGui : : Text ( " Selection range: %s - %s (%s) " , TimeToString ( s ) , TimeToString ( e ) , TimeToString ( e - s ) ) ;
}
else
{
ImGui : : Text ( " Selection range: none " ) ;
}
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (?) " ) ;
if ( ImGui : : IsItemHovered ( ) )
{
ImGui : : BeginTooltip ( ) ;
ImGui : : Text ( " Left draw on histogram to select range. Right click to clear selection. " ) ;
ImGui : : EndTooltip ( ) ;
}
if ( m_findZone . highlight . active )
{
ImGui : : Text ( " Selection time: %s " , TimeToString ( selectionTime ) ) ;
}
else
{
ImGui : : Text ( " Selection time: none " ) ;
}
2018-03-20 15:56:11 +00:00
if ( selThread ! = m_findZone . Unselected )
{
ImGui : : Text ( " Zone group time: %s " , TimeToString ( selBinTime ) ) ;
}
else
{
ImGui : : Text ( " Zone group time: none " ) ;
}
2018-03-05 19:23:58 +00:00
2018-03-18 01:43:17 +00:00
enum { Height = 200 } ;
const auto wpos = ImGui : : GetCursorScreenPos ( ) ;
2018-02-16 15:19:31 +00:00
2018-03-18 01:43:17 +00:00
ImGui : : InvisibleButton ( " ##histogram " , ImVec2 ( w , Height + round ( ty * 1.5 ) ) ) ;
const bool hover = ImGui : : IsItemHovered ( ) ;
2018-02-16 15:19:31 +00:00
2018-03-18 01:43:17 +00:00
auto draw = ImGui : : GetWindowDrawList ( ) ;
draw - > AddRectFilled ( wpos , wpos + ImVec2 ( w , Height ) , 0x22FFFFFF ) ;
draw - > AddRect ( wpos , wpos + ImVec2 ( w , Height ) , 0x88FFFFFF ) ;
2018-02-16 15:19:31 +00:00
2018-03-18 01:43:17 +00:00
if ( m_findZone . logVal )
2018-02-16 12:28:40 +00:00
{
2018-03-18 01:43:17 +00:00
const auto hAdj = double ( Height - 4 ) / log10 ( maxVal + 1 ) ;
for ( int i = 0 ; i < numBins ; i + + )
2018-02-16 12:28:40 +00:00
{
2018-03-20 15:28:55 +00:00
const auto val = cumulateTime ? binTime [ i ] : bins [ i ] ;
2018-03-18 01:43:17 +00:00
if ( val > 0 )
{
draw - > AddLine ( wpos + ImVec2 ( 2 + i , Height - 3 ) , wpos + ImVec2 ( 2 + i , Height - 3 - log10 ( val + 1 ) * hAdj ) , 0xFF22DDDD ) ;
2018-03-20 13:37:58 +00:00
if ( selBin [ i ] > 0 )
{
draw - > AddLine ( wpos + ImVec2 ( 2 + i , Height - 3 ) , wpos + ImVec2 ( 2 + i , Height - 3 - log10 ( selBin [ i ] + 1 ) * hAdj ) , 0xFFDD7777 ) ;
}
2018-03-18 01:43:17 +00:00
}
2018-02-16 12:28:40 +00:00
}
}
2018-03-18 01:43:17 +00:00
else
2018-02-16 12:09:24 +00:00
{
2018-03-18 01:43:17 +00:00
const auto hAdj = double ( Height - 4 ) / maxVal ;
for ( int i = 0 ; i < numBins ; i + + )
2018-02-16 12:28:40 +00:00
{
2018-03-20 15:28:55 +00:00
const auto val = cumulateTime ? binTime [ i ] : bins [ i ] ;
2018-03-18 01:43:17 +00:00
if ( val > 0 )
{
draw - > AddLine ( wpos + ImVec2 ( 2 + i , Height - 3 ) , wpos + ImVec2 ( 2 + i , Height - 3 - val * hAdj ) , 0xFF22DDDD ) ;
2018-03-20 13:37:58 +00:00
if ( selBin [ i ] > 0 )
{
draw - > AddLine ( wpos + ImVec2 ( 2 + i , Height - 3 ) , wpos + ImVec2 ( 2 + i , Height - 3 - selBin [ i ] * hAdj ) , 0xFFDD7777 ) ;
}
2018-03-18 01:43:17 +00:00
}
2018-02-16 12:28:40 +00:00
}
2018-02-16 12:09:24 +00:00
}
2018-02-20 15:01:33 +00:00
2018-03-18 01:43:17 +00:00
const auto xoff = 2 ;
const auto yoff = Height + 1 ;
2018-02-20 15:01:33 +00:00
2018-03-18 01:43:17 +00:00
if ( m_findZone . logTime )
{
const auto ltmin = log10 ( tmin ) ;
const auto ltmax = log10 ( tmax ) ;
const auto start = int ( floor ( ltmin ) ) ;
const auto end = int ( ceil ( ltmax ) ) ;
2018-02-28 14:20:52 +00:00
2018-03-18 01:43:17 +00:00
const auto range = ltmax - ltmin ;
const auto step = w / range ;
auto offset = start - ltmin ;
int tw = 0 ;
int tx = 0 ;
2018-02-28 14:20:52 +00:00
2018-03-18 01:43:17 +00:00
auto tt = int64_t ( pow ( 10 , start ) ) ;
2018-02-28 14:20:52 +00:00
2018-03-18 01:43:17 +00:00
static const double logticks [ ] = { log10 ( 2 ) , log10 ( 3 ) , log10 ( 4 ) , log10 ( 5 ) , log10 ( 6 ) , log10 ( 7 ) , log10 ( 8 ) , log10 ( 9 ) } ;
2018-02-28 14:20:52 +00:00
2018-03-18 01:43:17 +00:00
for ( int i = start ; i < = end ; i + + )
2018-02-28 14:20:52 +00:00
{
2018-03-18 01:43:17 +00:00
const auto x = ( i - start + offset ) * step ;
if ( x > = 0 )
2018-02-28 14:20:52 +00:00
{
2018-03-18 01:43:17 +00:00
draw - > AddLine ( wpos + ImVec2 ( x , yoff ) , wpos + ImVec2 ( x , yoff + round ( ty * 0.5 ) ) , 0x66FFFFFF ) ;
if ( tw = = 0 | | x > tx + tw + ty * 1.1 )
{
tx = x ;
auto txt = TimeToStringInteger ( tt ) ;
draw - > AddText ( wpos + ImVec2 ( x , yoff + round ( ty * 0.5 ) ) , 0x66FFFFFF , txt ) ;
tw = ImGui : : CalcTextSize ( txt ) . x ;
}
2018-02-28 14:20:52 +00:00
}
2018-03-18 01:43:17 +00:00
for ( int j = 0 ; j < 8 ; j + + )
2018-02-28 14:20:52 +00:00
{
2018-03-18 01:43:17 +00:00
const auto xoff = x + logticks [ j ] * step ;
if ( xoff > = 0 )
{
draw - > AddLine ( wpos + ImVec2 ( xoff , yoff ) , wpos + ImVec2 ( xoff , yoff + round ( ty * 0.25 ) ) , 0x66FFFFFF ) ;
}
2018-02-28 14:20:52 +00:00
}
2018-03-18 01:43:17 +00:00
tt * = 10 ;
}
2018-02-28 14:20:52 +00:00
}
2018-03-18 01:43:17 +00:00
else
{
const auto pxns = numBins / dt ;
const auto nspx = 1.0 / pxns ;
const auto scale = std : : max ( 0.0 , round ( log10 ( nspx ) + 2 ) ) ;
const auto step = pow ( 10 , scale ) ;
2018-02-20 15:01:33 +00:00
2018-03-18 01:43:17 +00:00
const auto dx = step * pxns ;
double x = 0 ;
int tw = 0 ;
int tx = 0 ;
2018-02-20 15:01:33 +00:00
2018-03-18 01:43:17 +00:00
const auto sstep = step / 10.0 ;
const auto sdx = dx / 10.0 ;
2018-02-20 15:01:33 +00:00
2018-03-18 01:43:17 +00:00
static const double linelen [ ] = { 0.5 , 0.25 , 0.25 , 0.25 , 0.25 , 0.375 , 0.25 , 0.25 , 0.25 , 0.25 } ;
2018-02-20 15:01:33 +00:00
2018-03-18 01:43:17 +00:00
int64_t tt = int64_t ( ceil ( tmin / sstep ) * sstep ) ;
const auto diff = tmin / sstep - int64_t ( tmin / sstep ) ;
const auto xo = ( diff = = 0 ? 0 : ( ( 1 - diff ) * sstep * pxns ) ) + xoff ;
int iter = int ( ceil ( ( tmin - int64_t ( tmin / step ) * step ) / sstep ) ) ;
2018-02-21 14:18:30 +00:00
2018-03-18 01:43:17 +00:00
while ( x < numBins )
2018-02-20 15:01:33 +00:00
{
2018-03-18 01:43:17 +00:00
draw - > AddLine ( wpos + ImVec2 ( xo + x , yoff ) , wpos + ImVec2 ( xo + x , yoff + round ( ty * linelen [ iter ] ) ) , 0x66FFFFFF ) ;
if ( iter = = 0 & & ( tw = = 0 | | x > tx + tw + ty * 1.1 ) )
{
tx = x ;
auto txt = TimeToStringInteger ( tt ) ;
draw - > AddText ( wpos + ImVec2 ( xo + x , yoff + round ( ty * 0.5 ) ) , 0x66FFFFFF , txt ) ;
tw = ImGui : : CalcTextSize ( txt ) . x ;
}
2018-02-20 15:01:33 +00:00
2018-03-18 01:43:17 +00:00
iter = ( iter + 1 ) % 10 ;
x + = sdx ;
tt + = sstep ;
}
2018-02-20 15:01:33 +00:00
}
2018-03-18 01:43:17 +00:00
if ( hover & & ImGui : : IsMouseHoveringRect ( wpos + ImVec2 ( 2 , 2 ) , wpos + ImVec2 ( w - 2 , Height + round ( ty * 1.5 ) ) ) )
{
const auto ltmin = log10 ( tmin ) ;
const auto ltmax = log10 ( tmax ) ;
2018-03-05 12:20:24 +00:00
2018-03-18 01:43:17 +00:00
auto & io = ImGui : : GetIO ( ) ;
draw - > AddLine ( ImVec2 ( io . MousePos . x , wpos . y ) , ImVec2 ( io . MousePos . x , wpos . y + Height - 2 ) , 0x33FFFFFF ) ;
2018-02-16 13:31:57 +00:00
2018-03-18 01:43:17 +00:00
const auto bin = double ( io . MousePos . x - wpos . x - 2 ) ;
int64_t t0 , t1 ;
if ( m_findZone . logTime )
{
t0 = int64_t ( pow ( 10 , ltmin + bin / numBins * ( ltmax - ltmin ) ) ) ;
t1 = int64_t ( pow ( 10 , ltmin + ( bin + 1 ) / numBins * ( ltmax - ltmin ) ) ) ;
}
else
{
t0 = int64_t ( tmin + bin / numBins * ( tmax - tmin ) ) ;
t1 = int64_t ( tmin + ( bin + 1 ) / numBins * ( tmax - tmin ) ) ;
}
2018-02-16 13:31:57 +00:00
2018-03-18 01:43:17 +00:00
int64_t tBefore = 0 ;
for ( int i = 0 ; i < bin ; i + + )
{
tBefore + = binTime [ i ] ;
}
2018-02-16 13:42:16 +00:00
2018-03-18 01:43:17 +00:00
int64_t tAfter = 0 ;
for ( int i = bin + 1 ; i < numBins ; i + + )
{
tAfter + = binTime [ i ] ;
}
2018-02-16 13:42:16 +00:00
2018-03-18 01:43:17 +00:00
ImGui : : BeginTooltip ( ) ;
ImGui : : Text ( " Time range: %s - %s " , TimeToString ( t0 ) , TimeToString ( t1 ) ) ;
ImGui : : Text ( " Count: % " PRIu64 , bins [ bin ] ) ;
ImGui : : Text ( " Time spent in bin: %s " , TimeToString ( binTime [ bin ] ) ) ;
ImGui : : Text ( " Time spent in the left bins: %s " , TimeToString ( tBefore ) ) ;
ImGui : : Text ( " Time spent in the right bins: %s " , TimeToString ( tAfter ) ) ;
ImGui : : EndTooltip ( ) ;
2018-03-04 21:52:36 +00:00
2018-03-18 01:43:17 +00:00
if ( ImGui : : IsMouseClicked ( 1 ) )
{
m_findZone . highlight . active = false ;
2018-03-18 15:41:58 +00:00
m_findZone . ResetThreads ( ) ;
2018-03-18 01:43:17 +00:00
}
else if ( ImGui : : IsMouseClicked ( 0 ) )
{
m_findZone . highlight . active = true ;
m_findZone . highlight . start = t0 ;
m_findZone . highlight . end = t1 ;
}
else if ( ImGui : : IsMouseDragging ( 0 , 0 ) )
{
m_findZone . highlight . end = t1 > m_findZone . highlight . start ? t1 : t0 ;
2018-03-18 15:41:58 +00:00
m_findZone . ResetThreads ( ) ;
2018-03-18 01:43:17 +00:00
}
2018-03-04 21:52:36 +00:00
}
2018-03-18 01:43:17 +00:00
if ( m_findZone . highlight . active & & m_findZone . highlight . start ! = m_findZone . highlight . end )
2018-03-04 21:52:36 +00:00
{
2018-03-18 01:43:17 +00:00
const auto s = std : : min ( m_findZone . highlight . start , m_findZone . highlight . end ) ;
const auto e = std : : max ( m_findZone . highlight . start , m_findZone . highlight . end ) ;
2018-03-04 21:52:36 +00:00
2018-03-18 01:43:17 +00:00
float t0 , t1 ;
if ( m_findZone . logTime )
{
const auto ltmin = log10 ( tmin ) ;
const auto ltmax = log10 ( tmax ) ;
2018-03-04 21:52:36 +00:00
2018-03-18 01:43:17 +00:00
t0 = ( log10 ( s ) - ltmin ) / float ( ltmax - ltmin ) * numBins ;
t1 = ( log10 ( e ) - ltmin ) / float ( ltmax - ltmin ) * numBins ;
}
else
{
t0 = ( s - tmin ) / float ( tmax - tmin ) * numBins ;
t1 = ( e - tmin ) / float ( tmax - tmin ) * numBins ;
}
2018-03-05 12:20:24 +00:00
2018-03-18 01:43:17 +00:00
draw - > AddRectFilled ( wpos + ImVec2 ( 2 + t0 , 1 ) , wpos + ImVec2 ( 2 + t1 , Height - 1 ) , 0x22DD8888 ) ;
draw - > AddRect ( wpos + ImVec2 ( 2 + t0 , 1 ) , wpos + ImVec2 ( 2 + t1 , Height - 1 ) , 0x44DD8888 ) ;
2018-03-04 21:52:36 +00:00
}
2018-02-16 13:31:57 +00:00
}
2018-02-15 16:25:16 +00:00
}
}
ImGui : : TreePop ( ) ;
}
ImGui : : Separator ( ) ;
2018-03-04 17:44:33 +00:00
ImGui : : Text ( " Found zones: " ) ;
2018-03-19 15:01:36 +00:00
ImGui : : SameLine ( ) ;
2018-03-20 13:37:58 +00:00
if ( ImGui : : SmallButton ( " Unselect " ) )
{
m_findZone . selThread = m_findZone . Unselected ;
}
ImGui : : SameLine ( ) ;
2018-03-19 15:01:36 +00:00
if ( m_findZone . showThreads )
{
if ( ImGui : : SmallButton ( " Group by user text " ) )
{
m_findZone . showThreads = false ;
2018-03-20 13:37:58 +00:00
m_findZone . selThread = m_findZone . Unselected ;
2018-03-19 15:01:36 +00:00
m_findZone . ResetThreads ( ) ;
}
}
else
{
if ( ImGui : : SmallButton ( " Group by threads " ) )
{
m_findZone . showThreads = true ;
2018-03-20 13:37:58 +00:00
m_findZone . selThread = m_findZone . Unselected ;
2018-03-19 15:01:36 +00:00
m_findZone . ResetThreads ( ) ;
}
}
2018-03-20 16:19:48 +00:00
ImGui : : SameLine ( ) ;
if ( m_findZone . sortByCounts )
{
if ( ImGui : : SmallButton ( " Sort by order " ) )
{
m_findZone . sortByCounts = false ;
}
}
else
{
if ( ImGui : : SmallButton ( " Sort by counts " ) )
{
m_findZone . sortByCounts = true ;
}
}
2018-03-04 17:44:33 +00:00
2018-03-18 19:20:24 +00:00
auto & zones = m_worker . GetZonesForSourceLocation ( m_findZone . match [ m_findZone . selMatch ] ) . zones ;
2018-03-18 15:41:58 +00:00
auto sz = zones . size ( ) ;
2018-03-18 20:03:36 +00:00
auto processed = m_findZone . processed ;
2018-03-20 15:28:55 +00:00
const auto hmin = std : : min ( m_findZone . highlight . start , m_findZone . highlight . end ) ;
const auto hmax = std : : max ( m_findZone . highlight . start , m_findZone . highlight . end ) ;
const auto showThreads = m_findZone . showThreads ;
const auto highlightActive = m_findZone . highlight . active ;
2018-03-18 20:03:36 +00:00
while ( processed < sz )
2018-02-15 16:25:16 +00:00
{
2018-03-18 20:03:36 +00:00
auto & ev = zones [ processed ] ;
2018-03-24 01:00:20 +00:00
if ( ev . zone - > end < 0 ) break ;
2018-03-18 15:41:58 +00:00
2018-03-18 19:45:49 +00:00
const auto end = m_worker . GetZoneEndDirect ( * ev . zone ) ;
const auto timespan = end - ev . zone - > start ;
2018-03-18 20:03:36 +00:00
if ( timespan = = 0 )
{
processed + + ;
continue ;
}
2018-03-18 15:41:58 +00:00
2018-03-20 15:28:55 +00:00
if ( highlightActive )
2018-03-18 15:41:58 +00:00
{
2018-03-20 15:28:55 +00:00
if ( timespan < hmin | | timespan > hmax )
2018-03-18 20:03:36 +00:00
{
processed + + ;
continue ;
}
2018-03-18 15:41:58 +00:00
}
2018-03-04 22:17:36 +00:00
2018-03-18 20:03:36 +00:00
processed + + ;
2018-03-20 15:28:55 +00:00
if ( showThreads )
2018-03-19 15:01:36 +00:00
{
m_findZone . threads [ ev . thread ] . push_back ( ev . zone ) ;
}
else
{
const uint64_t id = ev . zone - > text . active ? ev . zone - > text . idx : std : : numeric_limits < uint64_t > : : max ( ) ;
m_findZone . threads [ id ] . push_back ( ev . zone ) ;
}
2018-03-18 15:41:58 +00:00
}
2018-03-18 20:03:36 +00:00
m_findZone . processed = processed ;
2018-03-18 15:41:58 +00:00
2018-03-20 16:19:48 +00:00
Vector < decltype ( m_findZone . threads ) : : iterator > threads ;
threads . reserve_and_use ( m_findZone . threads . size ( ) ) ;
2018-03-18 15:41:58 +00:00
int idx = 0 ;
2018-03-20 16:19:48 +00:00
for ( auto it = m_findZone . threads . begin ( ) ; it ! = m_findZone . threads . end ( ) ; + + it )
{
threads [ idx + + ] = it ;
}
if ( m_findZone . sortByCounts )
{
std : : sort ( threads . begin ( ) , threads . end ( ) , [ ] ( const auto & lhs , const auto & rhs ) { return lhs - > second . size ( ) > rhs - > second . size ( ) ; } ) ;
}
ImGui : : BeginChild ( " ##zonesScroll " , ImVec2 ( ImGui : : GetWindowContentRegionWidth ( ) , std : : max ( 200.f , ImGui : : GetContentRegionAvail ( ) . y ) ) ) ;
for ( auto & v : threads )
2018-03-18 15:41:58 +00:00
{
2018-03-19 15:01:36 +00:00
const char * hdrString ;
2018-03-20 15:28:55 +00:00
if ( showThreads )
2018-03-19 15:01:36 +00:00
{
2018-03-20 16:19:48 +00:00
hdrString = m_worker . GetThreadString ( m_worker . DecompressThread ( v - > first ) ) ;
2018-03-19 15:01:36 +00:00
}
else
{
2018-03-20 16:19:48 +00:00
hdrString = v - > first = = std : : numeric_limits < uint64_t > : : max ( ) ? " No user text " : m_worker . GetString ( StringIdx ( v - > first ) ) ;
2018-03-19 15:01:36 +00:00
}
2018-03-20 16:19:48 +00:00
ImGui : : PushID ( v - > first ) ;
const bool expand = ImGui : : TreeNodeEx ( hdrString , ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ( v - > first = = m_findZone . selThread ? ImGuiTreeNodeFlags_Selected : 0 ) ) ;
2018-03-20 13:37:58 +00:00
if ( ImGui : : IsItemClicked ( ) )
{
2018-03-20 16:19:48 +00:00
m_findZone . selThread = v - > first ;
2018-03-20 13:37:58 +00:00
}
2018-03-04 17:52:32 +00:00
ImGui : : PopID ( ) ;
2018-02-15 16:25:16 +00:00
ImGui : : SameLine ( ) ;
2018-03-20 16:19:48 +00:00
ImGui : : TextColored ( ImVec4 ( 0.5f , 0.5f , 0.5f , 1.0f ) , " (%s) " , RealToString ( v - > second . size ( ) , true ) ) ;
2018-02-15 16:25:16 +00:00
if ( expand )
{
2018-03-19 15:01:36 +00:00
ImGui : : Columns ( 3 , hdrString ) ;
2018-02-15 16:25:16 +00:00
ImGui : : Separator ( ) ;
ImGui : : Text ( " Name " ) ;
2018-01-17 11:49:50 +00:00
ImGui : : NextColumn ( ) ;
2018-02-15 16:25:16 +00:00
ImGui : : Text ( " Time from start " ) ;
2018-01-17 11:49:50 +00:00
ImGui : : NextColumn ( ) ;
2018-02-15 16:25:16 +00:00
ImGui : : Text ( " Execution time " ) ;
ImGui : : NextColumn ( ) ;
ImGui : : Separator ( ) ;
2018-03-20 16:19:48 +00:00
for ( auto & ev : v - > second )
2018-02-15 16:25:16 +00:00
{
2018-03-18 01:53:16 +00:00
const auto end = m_worker . GetZoneEndDirect ( * ev ) ;
2018-03-04 22:07:38 +00:00
const auto timespan = end - ev - > start ;
2018-02-15 16:25:16 +00:00
ImGui : : PushID ( ev ) ;
2018-02-13 13:57:47 +00:00
auto & srcloc = m_worker . GetSourceLocation ( ev - > srcloc ) ;
if ( ImGui : : Selectable ( m_worker . GetString ( srcloc . name . active ? srcloc . name : srcloc . function ) , m_zoneInfoWindow = = ev , ImGuiSelectableFlags_SpanAllColumns ) )
2018-02-15 16:25:16 +00:00
{
m_zoneInfoWindow = ev ;
}
2018-03-04 17:42:18 +00:00
if ( ImGui : : IsItemHovered ( ) )
2018-03-04 17:35:40 +00:00
{
2018-03-04 17:42:18 +00:00
m_zoneHighlight = ev ;
if ( ImGui : : IsMouseClicked ( 2 ) )
{
ZoomToZone ( * ev ) ;
}
ZoneTooltip ( * ev ) ;
2018-03-04 17:35:40 +00:00
}
2018-01-17 11:49:50 +00:00
2018-02-15 16:25:16 +00:00
ImGui : : NextColumn ( ) ;
2018-02-13 13:57:47 +00:00
ImGui : : Text ( TimeToString ( ev - > start - m_worker . GetFrameBegin ( 0 ) ) ) ;
2018-02-15 16:25:16 +00:00
ImGui : : NextColumn ( ) ;
2018-03-04 22:07:38 +00:00
ImGui : : Text ( TimeToString ( timespan ) ) ;
2018-02-15 16:25:16 +00:00
ImGui : : NextColumn ( ) ;
ImGui : : PopID ( ) ;
}
ImGui : : Columns ( 1 ) ;
ImGui : : Separator ( ) ;
ImGui : : TreePop ( ) ;
2018-01-17 11:49:50 +00:00
}
}
2018-03-20 11:56:26 +00:00
ImGui : : EndChild ( ) ;
2018-01-17 11:49:50 +00:00
}
2018-03-18 11:55:54 +00:00
# endif
2018-01-17 11:49:50 +00:00
ImGui : : End ( ) ;
}
2018-03-24 13:40:48 +00:00
void View : : DrawStatistics ( )
{
ImGui : : Begin ( " Statistics " , & m_showStatistics ) ;
# ifdef TRACY_NO_STATISTICS
ImGui : : TextWrapped ( " Collection of statistical data is disabled in this build. " ) ;
ImGui : : TextWrapped ( " Rebuild without the TRACY_NO_STATISTICS macro to enable statistics view. " ) ;
# else
2018-03-24 14:16:43 +00:00
auto & slz = m_worker . GetSourceLocationZones ( ) ;
Vector < decltype ( slz . begin ( ) ) > srcloc ;
srcloc . reserve ( slz . size ( ) ) ;
for ( auto it = slz . begin ( ) ; it ! = slz . end ( ) ; + + it )
{
if ( it - > second . total ! = 0 )
{
srcloc . push_back_no_space_check ( it ) ;
}
}
2018-03-24 16:28:10 +00:00
switch ( m_statSort )
{
case 0 :
pdqsort_branchless ( srcloc . begin ( ) , srcloc . end ( ) , [ ] ( const auto & lhs , const auto & rhs ) { return lhs - > second . total > rhs - > second . total ; } ) ;
break ;
case 1 :
pdqsort_branchless ( srcloc . begin ( ) , srcloc . end ( ) , [ ] ( const auto & lhs , const auto & rhs ) { return lhs - > second . zones . size ( ) > rhs - > second . zones . size ( ) ; } ) ;
break ;
case 2 :
pdqsort_branchless ( srcloc . begin ( ) , srcloc . end ( ) , [ ] ( const auto & lhs , const auto & rhs ) { return lhs - > second . total / lhs - > second . zones . size ( ) > rhs - > second . total / rhs - > second . zones . size ( ) ; } ) ;
break ;
default :
assert ( false ) ;
break ;
}
2018-03-24 14:16:43 +00:00
ImGui : : Text ( " Recorded source locations: %s " , RealToString ( srcloc . size ( ) , true ) ) ;
ImGui : : Columns ( 5 ) ;
ImGui : : Separator ( ) ;
ImGui : : Text ( " Name " ) ;
ImGui : : NextColumn ( ) ;
ImGui : : Text ( " Location " ) ;
ImGui : : NextColumn ( ) ;
2018-03-24 16:28:10 +00:00
if ( ImGui : : Button ( " Total time " ) ) m_statSort = 0 ;
2018-03-24 14:16:43 +00:00
ImGui : : NextColumn ( ) ;
2018-03-24 16:28:10 +00:00
if ( ImGui : : Button ( " Counts " ) ) m_statSort = 1 ;
2018-03-24 14:16:43 +00:00
ImGui : : NextColumn ( ) ;
2018-03-24 16:28:10 +00:00
if ( ImGui : : Button ( " MTPC " ) ) m_statSort = 2 ;
2018-03-24 14:16:43 +00:00
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (?) " ) ;
if ( ImGui : : IsItemHovered ( ) )
{
ImGui : : BeginTooltip ( ) ;
ImGui : : Text ( " Mean time per call " ) ;
ImGui : : EndTooltip ( ) ;
}
ImGui : : NextColumn ( ) ;
ImGui : : Separator ( ) ;
for ( auto & v : srcloc )
{
ImGui : : PushID ( v - > first ) ;
auto & srcloc = m_worker . GetSourceLocation ( v - > first ) ;
2018-03-24 14:20:39 +00:00
auto name = m_worker . GetString ( srcloc . name . active ? srcloc . name : srcloc . function ) ;
2018-03-24 16:32:27 +00:00
if ( ImGui : : Selectable ( name , m_findZone . show & & ! m_findZone . match . empty ( ) & & m_findZone . match [ m_findZone . selMatch ] = = v - > first , ImGuiSelectableFlags_SpanAllColumns ) )
2018-03-24 14:16:43 +00:00
{
2018-03-24 14:20:39 +00:00
m_findZone . show = true ;
m_findZone . Reset ( ) ;
m_findZone . match . emplace_back ( v - > first ) ;
strcpy ( m_findZone . pattern , name ) ;
2018-03-24 14:16:43 +00:00
}
ImGui : : NextColumn ( ) ;
ImGui : : Text ( " %s:%i " , m_worker . GetString ( srcloc . file ) , srcloc . line ) ;
ImGui : : NextColumn ( ) ;
ImGui : : Text ( " %s " , TimeToString ( v - > second . total ) ) ;
ImGui : : NextColumn ( ) ;
ImGui : : Text ( " %s " , RealToString ( v - > second . zones . size ( ) , true ) ) ;
ImGui : : NextColumn ( ) ;
ImGui : : Text ( " %s " , TimeToString ( v - > second . total / v - > second . zones . size ( ) ) ) ;
ImGui : : NextColumn ( ) ;
ImGui : : PopID ( ) ;
}
2018-03-24 13:40:48 +00:00
# endif
ImGui : : End ( ) ;
}
2017-10-22 13:37:24 +00:00
uint32_t View : : GetZoneColor ( const ZoneEvent & ev )
2017-10-01 17:31:22 +00:00
{
2018-02-13 13:57:47 +00:00
const auto & srcloc = m_worker . GetSourceLocation ( ev . srcloc ) ;
2017-11-11 21:56:05 +00:00
const auto color = srcloc . color ;
return color ! = 0 ? ( color | 0xFF000000 ) : 0xFFCC5555 ;
2017-10-01 17:31:22 +00:00
}
2017-11-11 21:56:05 +00:00
uint32_t View : : GetZoneColor ( const GpuEvent & ev )
2017-10-01 17:31:22 +00:00
{
2018-02-13 13:57:47 +00:00
const auto & srcloc = m_worker . GetSourceLocation ( ev . srcloc ) ;
2017-11-05 19:54:49 +00:00
const auto color = srcloc . color ;
2017-11-11 21:56:05 +00:00
return color ! = 0 ? ( color | 0xFF000000 ) : 0xFF222288 ;
2017-10-01 17:31:22 +00:00
}
2017-10-22 13:37:24 +00:00
uint32_t View : : GetZoneHighlight ( const ZoneEvent & ev , bool migration )
2017-09-29 19:57:00 +00:00
{
if ( m_zoneInfoWindow = = & ev )
{
return 0xFF44DD44 ;
}
2017-09-29 20:38:38 +00:00
else if ( m_zoneHighlight = = & ev )
{
return 0xFF4444FF ;
}
2017-10-01 17:58:53 +00:00
else if ( migration )
{
return 0xFFDD22DD ;
}
2017-09-29 19:57:00 +00:00
else
{
2017-10-01 17:38:45 +00:00
const auto color = GetZoneColor ( ev ) ;
return 0xFF000000 |
( std : : min < int > ( 0xFF , ( ( ( color & 0x00FF0000 ) > > 16 ) + 25 ) ) < < 16 ) |
( std : : min < int > ( 0xFF , ( ( ( color & 0x0000FF00 ) > > 8 ) + 25 ) ) < < 8 ) |
( std : : min < int > ( 0xFF , ( ( ( color & 0x000000FF ) ) + 25 ) ) ) ;
2017-09-29 19:57:00 +00:00
}
}
2017-11-11 21:56:05 +00:00
uint32_t View : : GetZoneHighlight ( const GpuEvent & ev )
{
2017-11-12 00:25:44 +00:00
if ( m_gpuInfoWindow = = & ev )
{
return 0xFF44DD44 ;
}
2017-11-12 00:28:07 +00:00
else if ( m_gpuHighlight = = & ev )
{
return 0xFF4444FF ;
}
2017-11-12 00:25:44 +00:00
else
{
const auto color = GetZoneColor ( ev ) ;
return 0xFF000000 |
( std : : min < int > ( 0xFF , ( ( ( color & 0x00FF0000 ) > > 16 ) + 25 ) ) < < 16 ) |
( std : : min < int > ( 0xFF , ( ( ( color & 0x0000FF00 ) > > 8 ) + 25 ) ) < < 8 ) |
( std : : min < int > ( 0xFF , ( ( ( color & 0x000000FF ) ) + 25 ) ) ) ;
}
2017-11-11 21:56:05 +00:00
}
2017-10-22 13:37:24 +00:00
float View : : GetZoneThickness ( const ZoneEvent & ev )
2017-09-30 11:45:02 +00:00
{
if ( m_zoneInfoWindow = = & ev | | m_zoneHighlight = = & ev )
{
return 3.f ;
}
else
{
return 1.f ;
}
}
2017-11-11 21:56:05 +00:00
float View : : GetZoneThickness ( const GpuEvent & ev )
{
2017-11-12 00:28:07 +00:00
if ( m_gpuInfoWindow = = & ev | | m_gpuHighlight = = & ev )
2017-11-12 00:25:44 +00:00
{
return 3.f ;
}
else
{
return 1.f ;
}
2017-11-11 21:56:05 +00:00
}
2017-10-22 13:37:24 +00:00
void View : : ZoomToZone ( const ZoneEvent & ev )
2017-09-29 20:01:30 +00:00
{
2018-02-13 13:57:47 +00:00
const auto end = m_worker . GetZoneEnd ( ev ) ;
2017-10-08 09:38:03 +00:00
if ( end - ev . start < = 0 ) return ;
2017-11-27 21:12:26 +00:00
ZoomToRange ( ev . start , end ) ;
2017-09-29 20:01:30 +00:00
}
2017-11-11 21:56:05 +00:00
void View : : ZoomToZone ( const GpuEvent & ev )
{
2018-02-13 13:57:47 +00:00
const auto end = m_worker . GetZoneEnd ( ev ) ;
2017-11-11 21:56:05 +00:00
if ( end - ev . gpuStart < = 0 ) return ;
2017-11-27 21:12:26 +00:00
ZoomToRange ( ev . gpuStart , end ) ;
}
void View : : ZoomToRange ( int64_t start , int64_t end )
{
2017-11-27 21:41:30 +00:00
m_pause = true ;
m_zoomAnim . active = true ;
m_zoomAnim . start0 = m_zvStart ;
m_zoomAnim . start1 = start ;
m_zoomAnim . end0 = m_zvEnd ;
m_zoomAnim . end1 = end ;
m_zoomAnim . progress = 0 ;
const auto d0 = double ( m_zoomAnim . end0 - m_zoomAnim . start0 ) ;
const auto d1 = double ( m_zoomAnim . end1 - m_zoomAnim . start1 ) ;
const auto diff = d0 > d1 ? d0 / d1 : d1 / d0 ;
m_zoomAnim . lenMod = 10.0 / log10 ( diff ) ;
2017-11-11 21:56:05 +00:00
}
2017-10-22 13:37:24 +00:00
void View : : ZoneTooltip ( const ZoneEvent & ev )
2017-09-29 20:55:24 +00:00
{
2017-11-14 22:31:24 +00:00
int dmul = ev . text . active ? 2 : 1 ;
2017-09-29 20:55:24 +00:00
2018-03-19 15:08:50 +00:00
const auto tid = GetZoneThread ( ev ) ;
2018-02-13 13:57:47 +00:00
auto & srcloc = m_worker . GetSourceLocation ( ev . srcloc ) ;
2017-09-29 20:55:24 +00:00
2018-02-13 13:57:47 +00:00
const auto filename = m_worker . GetString ( srcloc . file ) ;
2017-09-29 20:55:24 +00:00
const auto line = srcloc . line ;
const char * func ;
const char * zoneName ;
2017-11-14 22:31:24 +00:00
if ( srcloc . name . active )
2017-09-29 20:55:24 +00:00
{
2018-02-13 13:57:47 +00:00
zoneName = m_worker . GetString ( srcloc . name ) ;
func = m_worker . GetString ( srcloc . function ) ;
2017-09-29 20:55:24 +00:00
}
else
{
2018-02-13 13:57:47 +00:00
func = zoneName = m_worker . GetString ( srcloc . function ) ;
2017-09-29 20:55:24 +00:00
}
2018-02-13 13:57:47 +00:00
const auto end = m_worker . GetZoneEnd ( ev ) ;
2017-09-29 20:55:24 +00:00
ImGui : : BeginTooltip ( ) ;
2017-11-17 23:51:04 +00:00
if ( srcloc . name . active )
{
ImGui : : Text ( " %s " , zoneName ) ;
ImGui : : Text ( " %s " , func ) ;
}
else
{
ImGui : : Text ( " %s " , func ) ;
}
2017-11-18 12:47:05 +00:00
ImGui : : Separator ( ) ;
2017-09-29 20:55:24 +00:00
ImGui : : Text ( " %s:%i " , filename , line ) ;
2018-03-19 15:08:50 +00:00
ImGui : : Text ( " Thread: %s " , m_worker . GetThreadString ( tid ) ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (0x% " PRIX64 " ) " , tid ) ;
2018-03-19 15:14:01 +00:00
ImGui : : Separator ( ) ;
2017-09-29 20:55:24 +00:00
ImGui : : Text ( " Execution time: %s " , TimeToString ( end - ev . start ) ) ;
2018-02-13 13:57:47 +00:00
ImGui : : Text ( " Without profiling: %s " , TimeToString ( end - ev . start - m_worker . GetDelay ( ) * dmul ) ) ;
2017-10-01 17:21:25 +00:00
if ( ev . cpu_start ! = - 1 )
{
2018-03-24 01:00:20 +00:00
if ( ev . end < 0 | | ev . cpu_start = = ev . cpu_end )
2017-10-01 17:21:25 +00:00
{
ImGui : : Text ( " CPU: %i " , ev . cpu_start ) ;
}
else
{
ImGui : : Text ( " CPU: %i -> %i " , ev . cpu_start , ev . cpu_end ) ;
}
}
2017-11-14 22:31:24 +00:00
if ( ev . text . active )
2017-09-29 20:55:24 +00:00
{
2017-10-28 19:50:06 +00:00
ImGui : : NewLine ( ) ;
2018-02-13 13:57:47 +00:00
ImGui : : TextColored ( ImVec4 ( 0xCC / 255.f , 0xCC / 255.f , 0x22 / 255.f , 1.f ) , " %s " , m_worker . GetString ( ev . text ) ) ;
2017-09-29 20:55:24 +00:00
}
ImGui : : EndTooltip ( ) ;
}
2017-11-11 21:56:05 +00:00
void View : : ZoneTooltip ( const GpuEvent & ev )
{
2018-03-19 15:13:12 +00:00
const auto tid = GetZoneThread ( ev ) ;
2018-02-13 13:57:47 +00:00
const auto & srcloc = m_worker . GetSourceLocation ( ev . srcloc ) ;
2017-11-11 21:56:05 +00:00
2018-02-13 13:57:47 +00:00
const auto name = m_worker . GetString ( srcloc . name ) ;
const auto filename = m_worker . GetString ( srcloc . file ) ;
2017-11-11 21:56:05 +00:00
const auto line = srcloc . line ;
2018-02-13 13:57:47 +00:00
const auto func = m_worker . GetString ( srcloc . function ) ;
2017-11-11 21:56:05 +00:00
2018-02-13 13:57:47 +00:00
const auto end = m_worker . GetZoneEnd ( ev ) ;
2017-11-11 21:56:05 +00:00
ImGui : : BeginTooltip ( ) ;
2017-11-18 12:47:05 +00:00
ImGui : : Text ( " %s " , name ) ;
2017-11-11 21:56:05 +00:00
ImGui : : Text ( " %s " , func ) ;
2017-11-17 23:51:04 +00:00
ImGui : : Separator ( ) ;
2017-11-11 21:56:05 +00:00
ImGui : : Text ( " %s:%i " , filename , line ) ;
2018-03-19 15:13:12 +00:00
ImGui : : Text ( " Thread: %s " , m_worker . GetThreadString ( tid ) ) ;
ImGui : : SameLine ( ) ;
ImGui : : TextDisabled ( " (0x% " PRIX64 " ) " , tid ) ;
2018-03-19 15:14:01 +00:00
ImGui : : Separator ( ) ;
2017-11-11 21:56:05 +00:00
ImGui : : Text ( " GPU execution time: %s " , TimeToString ( end - ev . gpuStart ) ) ;
ImGui : : Text ( " CPU command setup time: %s " , TimeToString ( ev . cpuEnd - ev . cpuStart ) ) ;
ImGui : : Text ( " Delay to execution: %s " , TimeToString ( ev . gpuStart - ev . cpuStart ) ) ;
ImGui : : EndTooltip ( ) ;
}
2017-10-22 14:15:27 +00:00
const ZoneEvent * View : : GetZoneParent ( const ZoneEvent & zone ) const
{
2018-02-13 13:57:47 +00:00
for ( const auto & thread : m_worker . GetThreadData ( ) )
2017-10-22 14:15:27 +00:00
{
const ZoneEvent * parent = nullptr ;
const Vector < ZoneEvent * > * timeline = & thread - > timeline ;
if ( timeline - > empty ( ) ) continue ;
for ( ; ; )
{
auto it = std : : upper_bound ( timeline - > begin ( ) , timeline - > end ( ) , zone . start , [ ] ( const auto & l , const auto & r ) { return l < r - > start ; } ) ;
if ( it ! = timeline - > begin ( ) ) - - it ;
2018-03-24 01:00:20 +00:00
if ( zone . end > = 0 & & ( * it ) - > start > zone . end ) break ;
2017-10-22 14:15:27 +00:00
if ( * it = = & zone ) return parent ;
if ( ( * it ) - > child . empty ( ) ) break ;
parent = * it ;
timeline = & parent - > child ;
}
}
return nullptr ;
}
2017-11-12 00:25:44 +00:00
const GpuEvent * View : : GetZoneParent ( const GpuEvent & zone ) const
{
2018-02-13 13:57:47 +00:00
for ( const auto & ctx : m_worker . GetGpuData ( ) )
2017-11-12 00:25:44 +00:00
{
const GpuEvent * parent = nullptr ;
const Vector < GpuEvent * > * timeline = & ctx - > timeline ;
if ( timeline - > empty ( ) ) continue ;
for ( ; ; )
{
auto it = std : : upper_bound ( timeline - > begin ( ) , timeline - > end ( ) , zone . gpuStart , [ ] ( const auto & l , const auto & r ) { return l < r - > gpuStart ; } ) ;
if ( it ! = timeline - > begin ( ) ) - - it ;
2018-03-24 01:00:20 +00:00
if ( zone . gpuEnd > = 0 & & ( * it ) - > gpuStart > zone . gpuEnd ) break ;
2017-11-12 00:25:44 +00:00
if ( * it = = & zone ) return parent ;
if ( ( * it ) - > child . empty ( ) ) break ;
parent = * it ;
timeline = & parent - > child ;
}
}
return nullptr ;
}
2018-03-18 15:38:42 +00:00
uint64_t View : : GetZoneThread ( const ZoneEvent & zone ) const
{
for ( const auto & thread : m_worker . GetThreadData ( ) )
{
const Vector < ZoneEvent * > * timeline = & thread - > timeline ;
if ( timeline - > empty ( ) ) continue ;
for ( ; ; )
{
auto it = std : : upper_bound ( timeline - > begin ( ) , timeline - > end ( ) , zone . start , [ ] ( const auto & l , const auto & r ) { return l < r - > start ; } ) ;
if ( it ! = timeline - > begin ( ) ) - - it ;
2018-03-24 01:00:20 +00:00
if ( zone . end > = 0 & & ( * it ) - > start > zone . end ) break ;
2018-03-18 15:38:42 +00:00
if ( * it = = & zone ) return thread - > id ;
if ( ( * it ) - > child . empty ( ) ) break ;
timeline = & ( * it ) - > child ;
}
}
return 0 ;
}
2018-03-19 15:11:37 +00:00
uint64_t View : : GetZoneThread ( const GpuEvent & zone ) const
{
for ( const auto & ctx : m_worker . GetGpuData ( ) )
{
const Vector < GpuEvent * > * timeline = & ctx - > timeline ;
if ( timeline - > empty ( ) ) continue ;
for ( ; ; )
{
auto it = std : : upper_bound ( timeline - > begin ( ) , timeline - > end ( ) , zone . gpuStart , [ ] ( const auto & l , const auto & r ) { return l < r - > gpuStart ; } ) ;
if ( it ! = timeline - > begin ( ) ) - - it ;
2018-03-24 01:00:20 +00:00
if ( zone . gpuEnd > = 0 & & ( * it ) - > gpuStart > zone . gpuEnd ) break ;
2018-03-19 15:11:37 +00:00
if ( * it = = & zone ) return ctx - > thread ;
if ( ( * it ) - > child . empty ( ) ) break ;
timeline = & ( * it ) - > child ;
}
}
return 0 ;
}
2018-03-18 11:55:54 +00:00
# ifndef TRACY_NO_STATISTICS
2018-01-17 11:49:50 +00:00
void View : : FindZones ( )
{
2018-03-18 15:07:07 +00:00
m_findZone . match = m_worker . GetMatchingSourceLocation ( m_findZone . pattern ) ;
if ( m_findZone . match . empty ( ) ) return ;
2018-03-04 20:10:10 +00:00
2018-03-18 15:07:07 +00:00
auto it = m_findZone . match . begin ( ) ;
while ( it ! = m_findZone . match . end ( ) )
2018-03-04 21:11:50 +00:00
{
2018-03-18 19:20:24 +00:00
if ( m_worker . GetZonesForSourceLocation ( * it ) . zones . empty ( ) )
2018-02-15 15:24:01 +00:00
{
2018-03-18 15:07:07 +00:00
it = m_findZone . match . erase ( it ) ;
}
else
{
+ + it ;
2018-02-15 15:24:01 +00:00
}
2018-01-17 11:49:50 +00:00
}
}
2018-03-18 11:55:54 +00:00
# endif
2018-01-17 11:49:50 +00:00
2017-09-12 23:33:50 +00:00
}