2017-09-12 23:54:22 +00:00
# ifdef _MSC_VER
# include <winsock2.h>
2017-11-26 15:42:50 +00:00
# include <intrin.h>
2017-09-12 23:54:22 +00:00
# else
# include <sys / time.h>
# endif
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>
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
2017-09-13 21:40:28 +00:00
# include "../common/TracyProtocol.hpp"
2017-09-12 23:33:50 +00:00
# include "../common/TracySystem.hpp"
2017-09-13 21:40:28 +00:00
# include "../common/TracyQueue.hpp"
2017-12-08 22:11:08 +00:00
# include "tracy_pdqsort.h"
2017-09-30 14:58:02 +00:00
# include "TracyFileRead.hpp"
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 )
{
sign = " - " ;
ns = - ns ;
}
if ( ns < 1000 )
{
2017-10-28 19:50:06 +00:00
sprintf ( buf , " %s% " PRIi64 " ns " , sign , ns ) ;
2017-10-22 15:47:40 +00:00
}
2017-10-28 19:50:06 +00:00
else if ( ns < 1000ll * 1000 )
2017-10-22 15:47:40 +00:00
{
sprintf ( buf , " %s%.2f us " , sign , ns / 1000. ) ;
}
2017-10-28 19:50:06 +00:00
else if ( ns < 1000ll * 1000 * 1000 )
2017-10-22 15:47:40 +00:00
{
sprintf ( buf , " %s%.2f ms " , sign , ns / ( 1000. * 1000. ) ) ;
}
2017-10-28 19:50:06 +00:00
else if ( ns < 1000ll * 1000 * 1000 * 60 )
2017-10-22 15:47:40 +00:00
{
sprintf ( buf , " %s%.2f s " , sign , ns / ( 1000. * 1000. * 1000. ) ) ;
}
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-22 15:47:40 +00:00
}
return buf ;
}
static const char * RealToString ( double val , bool separator )
{
enum { Pool = 8 } ;
static char bufpool [ Pool ] [ 64 ] ;
static int bufsel = 0 ;
char * buf = bufpool [ bufsel ] ;
bufsel = ( bufsel + 1 ) % Pool ;
sprintf ( buf , " %f " , val ) ;
auto ptr = buf ;
if ( * ptr = = ' - ' ) ptr + + ;
const auto vbegin = ptr ;
if ( separator )
{
while ( * ptr ! = ' \0 ' & & * ptr ! = ' , ' & & * ptr ! = ' . ' ) ptr + + ;
auto end = ptr ;
while ( * end ! = ' \0 ' ) end + + ;
auto sz = end - ptr ;
while ( ptr - vbegin > 3 )
{
ptr - = 3 ;
memmove ( ptr + 1 , ptr , sz ) ;
* ptr = ' , ' ;
sz + = 4 ;
}
}
while ( * ptr ! = ' \0 ' & & * ptr ! = ' , ' & & * ptr ! = ' . ' ) ptr + + ;
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-10-06 16:25:30 +00:00
enum { MinVisSize = 3 } ;
2017-09-12 23:33:50 +00:00
static View * s_instance = nullptr ;
View : : View ( const char * addr )
: m_addr ( addr )
, m_shutdown ( false )
2017-09-17 22:31:09 +00:00
, m_connected ( false )
2017-09-20 18:38:12 +00:00
, m_hasData ( false )
2017-09-30 14:58:02 +00:00
, m_staticView ( false )
2017-11-11 01:43:08 +00:00
, m_sourceLocationExpand ( { 0 } )
2017-09-25 21:38:49 +00:00
, m_zonesCnt ( 0 )
2017-09-15 00:29:48 +00:00
, m_mbps ( 64 )
2017-11-23 00:23:40 +00:00
, m_compRatio ( 1 )
2017-11-23 23:45:55 +00:00
, m_pendingStrings ( 0 )
, m_pendingThreads ( 0 )
2017-11-23 23:53:04 +00:00
, m_pendingSourceLocation ( 0 )
2017-09-17 11:10:42 +00:00
, m_stream ( LZ4_createStreamDecode ( ) )
2017-11-10 18:15:00 +00:00
, m_buffer ( new char [ TargetFrameSize * 3 + 1 ] )
2017-09-17 11:10:42 +00:00
, m_bufferOffset ( 0 )
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-12-09 19:05:34 +00:00
, m_lastTime ( 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-10-15 14:42:56 +00:00
, m_drawRegion ( false )
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 )
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-10-18 16:48:51 +00:00
, m_terminate ( false )
2017-09-12 23:33:50 +00:00
{
assert ( s_instance = = nullptr ) ;
s_instance = this ;
2017-09-19 22:46:30 +00:00
ImGuiStyle & style = ImGui : : GetStyle ( ) ;
style . FrameRounding = 2.f ;
2017-09-12 23:33:50 +00:00
m_thread = std : : thread ( [ this ] { Worker ( ) ; } ) ;
SetThreadName ( m_thread , " Tracy View " ) ;
}
2017-09-30 14:58:02 +00:00
View : : View ( FileRead & f )
: m_shutdown ( false )
, m_connected ( false )
, m_hasData ( true )
, m_staticView ( true )
, m_zonesCnt ( 0 )
2017-09-30 17:21:51 +00:00
, m_stream ( nullptr )
, m_buffer ( nullptr )
2017-09-30 14:58:02 +00:00
, m_frameScale ( 0 )
, m_pause ( false )
, m_frameStart ( 0 )
, m_zvStart ( 0 )
, m_zvEnd ( 0 )
2017-10-12 20:27:17 +00:00
, m_zvHeight ( 0 )
, m_zvScroll ( 0 )
2017-09-30 14:58:02 +00:00
, m_zoneInfoWindow ( nullptr )
2017-11-12 00:25:44 +00:00
, m_gpuInfoWindow ( nullptr )
2017-10-15 14:42:56 +00:00
, m_drawRegion ( false )
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 )
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-10-18 16:48:51 +00:00
, m_terminate ( false )
2017-09-30 14:58:02 +00:00
{
assert ( s_instance = = nullptr ) ;
s_instance = this ;
f . Read ( & m_delay , sizeof ( m_delay ) ) ;
f . Read ( & m_resolution , sizeof ( m_resolution ) ) ;
f . Read ( & m_timerMul , sizeof ( m_timerMul ) ) ;
2017-12-09 19:05:34 +00:00
f . Read ( & m_lastTime , sizeof ( m_lastTime ) ) ;
2017-09-30 14:58:02 +00:00
uint64_t sz ;
2017-10-03 21:29:48 +00:00
{
f . Read ( & sz , sizeof ( sz ) ) ;
assert ( sz < 1024 ) ;
char tmp [ 1024 ] ;
f . Read ( tmp , sz ) ;
m_captureName = std : : string ( tmp , tmp + sz ) ;
}
2017-09-30 14:58:02 +00:00
f . Read ( & sz , sizeof ( sz ) ) ;
2017-09-30 23:54:40 +00:00
m_frames . reserve ( sz ) ;
2017-09-30 14:58:02 +00:00
for ( uint64_t i = 0 ; i < sz ; i + + )
{
uint64_t v ;
f . Read ( & v , sizeof ( v ) ) ;
m_frames . push_back ( v ) ;
}
2017-11-10 17:24:20 +00:00
std : : unordered_map < uint64_t , const char * > pointerMap ;
2017-09-30 14:58:02 +00:00
f . Read ( & sz , sizeof ( sz ) ) ;
for ( uint64_t i = 0 ; i < sz ; i + + )
{
uint64_t ptr ;
f . Read ( & ptr , sizeof ( ptr ) ) ;
uint64_t ssz ;
f . Read ( & ssz , sizeof ( ssz ) ) ;
2017-10-21 11:01:57 +00:00
auto dst = m_slab . Alloc < char > ( ssz + 1 ) ;
2017-09-30 14:58:02 +00:00
f . Read ( dst , ssz ) ;
dst [ ssz ] = ' \0 ' ;
2017-11-10 16:45:19 +00:00
m_stringData . push_back ( dst ) ;
2017-11-10 17:24:20 +00:00
pointerMap . emplace ( ptr , dst ) ;
2017-09-30 14:58:02 +00:00
}
2017-11-10 18:30:04 +00:00
f . Read ( & sz , sizeof ( sz ) ) ;
for ( uint64_t i = 0 ; i < sz ; i + + )
{
uint64_t id , ptr ;
f . Read ( & id , sizeof ( id ) ) ;
f . Read ( & ptr , sizeof ( ptr ) ) ;
m_strings . emplace ( id , pointerMap . find ( ptr ) - > second ) ;
}
2017-11-10 18:24:12 +00:00
f . Read ( & sz , sizeof ( sz ) ) ;
for ( uint64_t i = 0 ; i < sz ; i + + )
{
uint64_t id , ptr ;
f . Read ( & id , sizeof ( id ) ) ;
f . Read ( & ptr , sizeof ( ptr ) ) ;
m_threadNames . emplace ( id , pointerMap . find ( ptr ) - > second ) ;
}
2017-09-30 14:58:02 +00:00
f . Read ( & sz , sizeof ( sz ) ) ;
for ( uint64_t i = 0 ; i < sz ; i + + )
{
uint64_t ptr ;
f . Read ( & ptr , sizeof ( ptr ) ) ;
2017-11-05 19:54:49 +00:00
SourceLocation srcloc ;
2017-09-30 14:58:02 +00:00
f . Read ( & srcloc , sizeof ( srcloc ) ) ;
m_sourceLocation . emplace ( ptr , srcloc ) ;
}
2017-10-28 20:14:01 +00:00
f . Read ( & sz , sizeof ( sz ) ) ;
m_sourceLocationExpand . reserve ( sz ) ;
for ( uint64_t i = 0 ; i < sz ; i + + )
{
uint64_t v ;
f . Read ( & v , sizeof ( v ) ) ;
m_sourceLocationExpand . push_back ( v ) ;
}
2017-11-05 20:36:22 +00:00
f . Read ( & sz , sizeof ( sz ) ) ;
m_sourceLocationPayload . reserve ( sz ) ;
for ( uint64_t i = 0 ; i < sz ; i + + )
{
auto srcloc = m_slab . Alloc < SourceLocation > ( ) ;
2017-11-11 01:02:47 +00:00
f . Read ( srcloc , sizeof ( * srcloc ) ) ;
2017-11-05 20:36:22 +00:00
m_sourceLocationPayload . push_back ( srcloc ) ;
}
2017-10-04 18:10:38 +00:00
f . Read ( & sz , sizeof ( sz ) ) ;
for ( uint64_t i = 0 ; i < sz ; i + + )
{
LockMap lockmap ;
2017-10-14 13:21:15 +00:00
uint32_t id ;
uint64_t tsz ;
2017-10-04 18:10:38 +00:00
f . Read ( & id , sizeof ( id ) ) ;
2017-10-04 19:36:47 +00:00
f . Read ( & lockmap . srcloc , sizeof ( lockmap . srcloc ) ) ;
2017-12-10 20:37:39 +00:00
f . Read ( & lockmap . type , sizeof ( lockmap . type ) ) ;
f . Read ( & lockmap . valid , sizeof ( lockmap . valid ) ) ;
2017-10-04 18:10:38 +00:00
f . Read ( & tsz , sizeof ( tsz ) ) ;
for ( uint64_t i = 0 ; i < tsz ; i + + )
{
uint64_t t ;
f . Read ( & t , sizeof ( t ) ) ;
2017-10-08 21:03:38 +00:00
lockmap . threadMap . emplace ( t , lockmap . threadList . size ( ) ) ;
lockmap . threadList . emplace_back ( t ) ;
2017-10-04 18:10:38 +00:00
}
f . Read ( & tsz , sizeof ( tsz ) ) ;
2017-12-05 20:55:00 +00:00
lockmap . timeline . reserve ( tsz ) ;
2017-12-17 17:44:31 +00:00
if ( lockmap . type = = LockType : : Lockable )
2017-10-04 18:10:38 +00:00
{
2017-12-17 17:44:31 +00:00
for ( uint64_t i = 0 ; i < tsz ; i + + )
{
auto lev = m_slab . Alloc < LockEvent > ( ) ;
f . Read ( lev , sizeof ( LockEvent ) ) ;
lockmap . timeline . push_back ( lev ) ;
}
}
else
{
for ( uint64_t i = 0 ; i < tsz ; i + + )
{
auto lev = m_slab . Alloc < LockEventShared > ( ) ;
f . Read ( lev , sizeof ( LockEventShared ) ) ;
lockmap . timeline . push_back ( lev ) ;
}
2017-10-04 18:10:38 +00:00
}
2017-10-22 11:25:58 +00:00
lockmap . visible = true ;
2017-10-04 18:10:38 +00:00
m_lockMap . emplace ( id , std : : move ( lockmap ) ) ;
}
2017-10-14 13:26:02 +00:00
std : : unordered_map < uint64_t , MessageData * > msgMap ;
f . Read ( & sz , sizeof ( sz ) ) ;
m_messages . reserve ( sz ) ;
for ( uint64_t i = 0 ; i < sz ; i + + )
{
2017-11-11 01:42:17 +00:00
uint64_t ptr ;
2017-10-14 13:26:02 +00:00
f . Read ( & ptr , sizeof ( ptr ) ) ;
2017-10-21 11:01:57 +00:00
auto msgdata = m_slab . Alloc < MessageData > ( ) ;
2017-11-11 00:39:34 +00:00
f . Read ( msgdata , sizeof ( * msgdata ) ) ;
2017-10-14 13:26:02 +00:00
m_messages . push_back ( msgdata ) ;
msgMap . emplace ( ptr , msgdata ) ;
}
2017-09-30 14:58:02 +00:00
f . Read ( & sz , sizeof ( sz ) ) ;
2017-09-30 23:54:40 +00:00
m_threads . reserve ( sz ) ;
2017-09-30 14:58:02 +00:00
for ( uint64_t i = 0 ; i < sz ; i + + )
{
2017-10-21 11:01:57 +00:00
auto td = m_slab . AllocInit < ThreadData > ( ) ;
2017-09-30 14:58:02 +00:00
f . Read ( & td - > id , sizeof ( td - > id ) ) ;
2017-11-18 00:14:16 +00:00
f . Read ( & td - > count , sizeof ( td - > count ) ) ;
2017-11-10 17:22:41 +00:00
ReadTimeline ( f , td - > timeline ) ;
2017-10-14 13:26:02 +00:00
uint64_t msz ;
f . Read ( & msz , sizeof ( msz ) ) ;
td - > messages . reserve ( msz ) ;
for ( uint64_t j = 0 ; j < msz ; j + + )
{
uint64_t ptr ;
f . Read ( & ptr , sizeof ( ptr ) ) ;
td - > messages . push_back ( msgMap [ ptr ] ) ;
}
2017-10-22 11:13:26 +00:00
td - > showFull = true ;
td - > visible = true ;
2017-09-30 14:58:02 +00:00
m_threads . push_back ( td ) ;
}
2017-10-13 14:04:20 +00:00
2017-11-12 00:12:28 +00:00
f . Read ( & sz , sizeof ( sz ) ) ;
m_gpuData . reserve ( sz ) ;
for ( uint64_t i = 0 ; i < sz ; i + + )
{
auto ctx = m_slab . AllocInit < GpuCtxData > ( ) ;
2017-11-13 23:48:26 +00:00
f . Read ( & ctx - > thread , sizeof ( ctx - > thread ) ) ;
2017-11-17 23:32:15 +00:00
f . Read ( & ctx - > accuracyBits , sizeof ( ctx - > accuracyBits ) ) ;
2017-11-18 00:07:28 +00:00
f . Read ( & ctx - > count , sizeof ( ctx - > count ) ) ;
2017-11-12 00:12:28 +00:00
ReadTimeline ( f , ctx - > timeline ) ;
ctx - > showFull = true ;
2017-11-30 14:31:31 +00:00
ctx - > visible = true ;
2017-11-12 00:12:28 +00:00
m_gpuData . push_back ( ctx ) ;
}
2017-10-13 14:04:20 +00:00
f . Read ( & sz , sizeof ( sz ) ) ;
m_plots . reserve ( sz ) ;
for ( uint64_t i = 0 ; i < sz ; i + + )
{
2017-10-21 11:01:57 +00:00
auto pd = m_slab . AllocInit < PlotData > ( ) ;
2017-10-13 14:04:20 +00:00
f . Read ( & pd - > name , sizeof ( pd - > name ) ) ;
f . Read ( & pd - > min , sizeof ( pd - > min ) ) ;
f . Read ( & pd - > max , sizeof ( pd - > max ) ) ;
2017-10-22 11:17:34 +00:00
pd - > showFull = true ;
pd - > visible = true ;
2017-10-13 14:04:20 +00:00
uint64_t psz ;
f . Read ( & psz , sizeof ( psz ) ) ;
2017-12-05 20:24:09 +00:00
pd - > data . reserve_and_use ( psz ) ;
f . Read ( pd - > data . data ( ) , psz * sizeof ( PlotItem ) ) ;
2017-10-13 14:04:20 +00:00
m_plots . push_back ( pd ) ;
}
2017-09-30 14:58:02 +00:00
}
2017-09-12 23:33:50 +00:00
View : : ~ View ( )
{
m_shutdown . store ( true , std : : memory_order_relaxed ) ;
2017-09-30 14:58:02 +00:00
if ( ! m_staticView )
{
m_thread . join ( ) ;
}
2017-09-13 21:36:40 +00:00
2017-09-17 11:10:42 +00:00
delete [ ] m_buffer ;
LZ4_freeStreamDecode ( m_stream ) ;
2017-09-13 21:36:40 +00:00
assert ( s_instance ! = nullptr ) ;
s_instance = nullptr ;
2017-09-12 23:33:50 +00:00
}
2017-09-13 00:08:35 +00:00
bool View : : ShouldExit ( )
{
return s_instance - > m_shutdown . load ( std : : memory_order_relaxed ) ;
}
2017-09-12 23:33:50 +00:00
void View : : Worker ( )
{
2017-09-12 23:54:22 +00:00
timeval tv ;
tv . tv_sec = 0 ;
tv . tv_usec = 10000 ;
2017-09-12 23:33:50 +00:00
for ( ; ; )
{
if ( m_shutdown . load ( std : : memory_order_relaxed ) ) return ;
2017-09-14 00:15:04 +00:00
if ( ! m_sock . Connect ( m_addr . c_str ( ) , " 8086 " ) ) continue ;
2017-09-12 23:54:22 +00:00
2017-09-15 19:09:19 +00:00
std : : chrono : : time_point < std : : chrono : : high_resolution_clock > t0 ;
2017-09-15 20:45:03 +00:00
uint64_t bytes = 0 ;
2017-11-23 00:23:40 +00:00
uint64_t decBytes = 0 ;
2017-09-13 00:08:35 +00:00
2017-09-24 14:10:28 +00:00
{
WelcomeMessage welcome ;
if ( ! m_sock . Read ( & welcome , sizeof ( welcome ) , & tv , ShouldExit ) ) goto close ;
2017-09-25 22:13:24 +00:00
m_timerMul = welcome . timerMul ;
2017-10-16 23:10:38 +00:00
m_frames . push_back ( welcome . initBegin * m_timerMul ) ;
m_frames . push_back ( welcome . initEnd * m_timerMul ) ;
2017-12-09 19:05:34 +00:00
m_lastTime = m_frames . back ( ) ;
2017-09-25 22:13:24 +00:00
m_delay = welcome . delay * m_timerMul ;
2017-09-29 16:32:07 +00:00
m_resolution = welcome . resolution * m_timerMul ;
2017-10-03 21:26:41 +00:00
char dtmp [ 64 ] ;
time_t date = welcome . epoch ;
auto lt = localtime ( & date ) ;
strftime ( dtmp , 64 , " %F %T " , lt ) ;
char tmp [ 1024 ] ;
sprintf ( tmp , " %s @ %s###Profiler " , welcome . programName , dtmp ) ;
m_captureName = tmp ;
2017-09-24 14:10:28 +00:00
}
2017-09-12 23:54:22 +00:00
2017-09-20 18:38:12 +00:00
m_hasData . store ( true , std : : memory_order_release ) ;
2017-09-15 22:40:51 +00:00
2017-09-20 18:38:12 +00:00
LZ4_setStreamDecode ( m_stream , nullptr , 0 ) ;
2017-09-17 22:31:09 +00:00
m_connected . store ( true , std : : memory_order_relaxed ) ;
2017-09-15 19:09:19 +00:00
t0 = std : : chrono : : high_resolution_clock : : now ( ) ;
2017-09-15 00:29:48 +00:00
2017-09-12 23:54:22 +00:00
for ( ; ; )
{
if ( m_shutdown . load ( std : : memory_order_relaxed ) ) return ;
2017-09-13 21:40:28 +00:00
2017-11-10 16:34:11 +00:00
auto buf = m_buffer + m_bufferOffset ;
char lz4buf [ LZ4Size ] ;
lz4sz_t lz4sz ;
if ( ! m_sock . Read ( & lz4sz , sizeof ( lz4sz ) , & tv , ShouldExit ) ) goto close ;
if ( ! m_sock . Read ( lz4buf , lz4sz , & tv , ShouldExit ) ) goto close ;
bytes + = sizeof ( lz4sz ) + lz4sz ;
2017-09-17 11:10:42 +00:00
2017-11-10 16:34:11 +00:00
auto sz = LZ4_decompress_safe_continue ( m_stream , lz4buf , buf , lz4sz , TargetFrameSize ) ;
assert ( sz > = 0 ) ;
2017-11-23 00:23:40 +00:00
decBytes + = sz ;
2017-11-10 16:34:11 +00:00
2017-11-10 18:15:00 +00:00
char * ptr = buf ;
2017-11-10 16:34:11 +00:00
const char * end = buf + sz ;
2017-11-15 21:33:11 +00:00
2017-09-13 21:40:28 +00:00
{
2017-11-15 21:33:11 +00:00
std : : lock_guard < NonRecursiveBenaphore > lock ( m_lock ) ;
while ( ptr < end )
{
auto ev = ( const QueueItem * ) ptr ;
DispatchProcess ( * ev , ptr ) ;
}
2017-09-15 00:29:48 +00:00
2017-11-15 21:33:11 +00:00
m_bufferOffset + = sz ;
if ( m_bufferOffset > TargetFrameSize * 2 ) m_bufferOffset = 0 ;
2017-11-10 16:34:11 +00:00
2017-11-15 21:33:11 +00:00
HandlePostponedPlots ( ) ;
}
2017-10-19 21:26:21 +00:00
2017-09-15 00:29:48 +00:00
auto t1 = std : : chrono : : high_resolution_clock : : now ( ) ;
auto td = std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( t1 - t0 ) . count ( ) ;
enum { MbpsUpdateTime = 200 } ;
if ( td > MbpsUpdateTime )
{
2017-11-15 20:49:41 +00:00
std : : lock_guard < NonRecursiveBenaphore > lock ( m_mbpslock ) ;
2017-09-15 00:29:48 +00:00
m_mbps . erase ( m_mbps . begin ( ) ) ;
2017-09-15 23:47:04 +00:00
m_mbps . emplace_back ( bytes / ( td * 125.f ) ) ;
2017-11-23 00:23:40 +00:00
m_compRatio = float ( bytes ) / decBytes ;
2017-09-15 00:29:48 +00:00
t0 = t1 ;
bytes = 0 ;
2017-11-23 00:23:40 +00:00
decBytes = 0 ;
2017-09-15 00:29:48 +00:00
}
2017-10-18 16:48:51 +00:00
if ( m_terminate )
{
2017-11-23 23:53:04 +00:00
if ( m_pendingStrings ! = 0 | | m_pendingThreads ! = 0 | | m_pendingSourceLocation ! = 0 | |
2017-11-11 14:41:21 +00:00
! m_pendingCustomStrings . empty ( ) | | ! m_pendingPlots . empty ( ) )
2017-10-18 16:48:51 +00:00
{
continue ;
}
bool done = true ;
2017-11-19 00:16:21 +00:00
for ( auto & v : m_threads )
2017-10-18 16:48:51 +00:00
{
2017-11-19 00:16:21 +00:00
if ( ! v - > stack . empty ( ) )
2017-10-18 16:48:51 +00:00
{
done = false ;
break ;
}
}
if ( ! done ) continue ;
ServerQuery ( ServerQueryTerminate , 0 ) ;
break ;
}
2017-09-12 23:54:22 +00:00
}
2017-09-13 00:00:22 +00:00
close :
2017-09-14 00:15:04 +00:00
m_sock . Close ( ) ;
2017-09-17 22:31:09 +00:00
m_connected . store ( false , std : : memory_order_relaxed ) ;
2017-09-12 23:33:50 +00:00
}
}
2017-11-10 18:15:00 +00:00
void View : : DispatchProcess ( const QueueItem & ev , char * & ptr )
2017-09-14 17:44:49 +00:00
{
2017-11-11 14:41:21 +00:00
if ( ev . hdr . type = = QueueType : : CustomStringData | | ev . hdr . type = = QueueType : : StringData | | ev . hdr . type = = QueueType : : ThreadName | | ev . hdr . type = = QueueType : : PlotName | | ev . hdr . type = = QueueType : : SourceLocationPayload )
2017-09-14 17:44:49 +00:00
{
2017-11-19 12:22:08 +00:00
ptr + = sizeof ( QueueHeader ) + sizeof ( QueueStringTransfer ) ;
2017-09-14 17:44:49 +00:00
uint16_t sz ;
memcpy ( & sz , ptr , sizeof ( sz ) ) ;
ptr + = sizeof ( sz ) ;
2017-11-05 15:14:51 +00:00
switch ( ev . hdr . type )
2017-09-27 00:18:17 +00:00
{
2017-11-05 15:14:51 +00:00
case QueueType : : CustomStringData :
2017-11-10 17:39:43 +00:00
AddCustomString ( ev . stringTransfer . ptr , ptr , sz ) ;
2017-11-05 15:14:51 +00:00
break ;
case QueueType : : StringData :
2017-11-10 18:30:04 +00:00
AddString ( ev . stringTransfer . ptr , ptr , sz ) ;
2017-11-05 15:14:51 +00:00
break ;
case QueueType : : ThreadName :
2017-11-10 18:24:12 +00:00
AddThreadString ( ev . stringTransfer . ptr , ptr , sz ) ;
2017-11-05 15:14:51 +00:00
break ;
case QueueType : : PlotName :
2017-11-10 18:41:37 +00:00
HandlePlotName ( ev . stringTransfer . ptr , ptr , sz ) ;
2017-11-05 15:14:51 +00:00
break ;
2017-11-05 15:46:00 +00:00
case QueueType : : SourceLocationPayload :
AddSourceLocationPayload ( ev . stringTransfer . ptr , ptr , sz ) ;
break ;
2017-11-05 15:14:51 +00:00
default :
assert ( false ) ;
break ;
2017-10-14 12:28:04 +00:00
}
2017-09-14 17:44:49 +00:00
ptr + = sz ;
}
else
{
2017-11-19 12:22:08 +00:00
ptr + = QueueDataSize [ ev . hdr . idx ] ;
2017-09-14 17:44:49 +00:00
Process ( ev ) ;
}
}
2017-09-27 00:44:16 +00:00
void View : : ServerQuery ( uint8_t type , uint64_t data )
{
enum { DataSize = sizeof ( type ) + sizeof ( data ) } ;
char tmp [ DataSize ] ;
memcpy ( tmp , & type , sizeof ( type ) ) ;
memcpy ( tmp + sizeof ( type ) , & data , sizeof ( data ) ) ;
m_sock . Send ( tmp , DataSize ) ;
}
2017-09-13 21:40:28 +00:00
void View : : Process ( const QueueItem & ev )
{
2017-09-14 00:00:13 +00:00
switch ( ev . hdr . type )
{
case QueueType : : ZoneBegin :
2017-10-03 14:41:32 +00:00
ProcessZoneBegin ( ev . zoneBegin ) ;
2017-09-14 00:00:13 +00:00
break ;
2017-11-05 14:04:55 +00:00
case QueueType : : ZoneBeginAllocSrcLoc :
ProcessZoneBeginAllocSrcLoc ( ev . zoneBegin ) ;
break ;
2017-09-14 00:00:13 +00:00
case QueueType : : ZoneEnd :
2017-10-03 14:41:32 +00:00
ProcessZoneEnd ( ev . zoneEnd ) ;
2017-09-14 00:00:13 +00:00
break ;
2017-09-28 19:20:33 +00:00
case QueueType : : FrameMarkMsg :
2017-10-03 14:41:32 +00:00
ProcessFrameMark ( ev . frameMark ) ;
2017-09-15 22:30:27 +00:00
break ;
2017-09-26 00:28:14 +00:00
case QueueType : : SourceLocation :
2017-10-03 14:41:32 +00:00
AddSourceLocation ( ev . srcloc ) ;
2017-09-26 00:28:14 +00:00
break ;
2017-09-27 00:18:17 +00:00
case QueueType : : ZoneText :
2017-10-03 14:41:32 +00:00
ProcessZoneText ( ev . zoneText ) ;
2017-09-27 00:18:17 +00:00
break ;
2017-12-10 20:37:39 +00:00
case QueueType : : LockAnnounce :
ProcessLockAnnounce ( ev . lockAnnounce ) ;
break ;
2017-10-04 14:45:46 +00:00
case QueueType : : LockWait :
2017-10-04 16:32:22 +00:00
ProcessLockWait ( ev . lockWait ) ;
2017-10-04 14:45:46 +00:00
break ;
case QueueType : : LockObtain :
2017-10-04 16:32:22 +00:00
ProcessLockObtain ( ev . lockObtain ) ;
2017-10-04 14:45:46 +00:00
break ;
case QueueType : : LockRelease :
2017-10-04 16:32:22 +00:00
ProcessLockRelease ( ev . lockRelease ) ;
2017-10-04 14:45:46 +00:00
break ;
2017-12-10 21:04:49 +00:00
case QueueType : : LockSharedWait :
ProcessLockSharedWait ( ev . lockWait ) ;
break ;
case QueueType : : LockSharedObtain :
ProcessLockSharedObtain ( ev . lockObtain ) ;
break ;
case QueueType : : LockSharedRelease :
ProcessLockSharedRelease ( ev . lockRelease ) ;
break ;
2017-10-06 15:05:14 +00:00
case QueueType : : LockMark :
ProcessLockMark ( ev . lockMark ) ;
break ;
2017-10-13 01:36:59 +00:00
case QueueType : : PlotData :
ProcessPlotData ( ev . plotData ) ;
break ;
2017-10-14 12:28:04 +00:00
case QueueType : : Message :
2017-10-21 10:39:26 +00:00
ProcessMessage ( ev . message ) ;
2017-10-15 11:06:49 +00:00
break ;
case QueueType : : MessageLiteral :
2017-10-21 10:39:26 +00:00
ProcessMessageLiteral ( ev . message ) ;
2017-10-14 12:28:04 +00:00
break ;
2017-11-11 18:44:09 +00:00
case QueueType : : GpuNewContext :
ProcessGpuNewContext ( ev . gpuNewContext ) ;
break ;
2017-11-11 20:09:48 +00:00
case QueueType : : GpuZoneBegin :
ProcessGpuZoneBegin ( ev . gpuZoneBegin ) ;
break ;
case QueueType : : GpuZoneEnd :
ProcessGpuZoneEnd ( ev . gpuZoneEnd ) ;
break ;
2017-11-11 21:08:47 +00:00
case QueueType : : GpuTime :
ProcessGpuTime ( ev . gpuTime ) ;
break ;
2017-11-25 12:33:57 +00:00
case QueueType : : GpuResync :
ProcessGpuResync ( ev . gpuResync ) ;
break ;
2017-10-18 16:48:51 +00:00
case QueueType : : Terminate :
m_terminate = true ;
break ;
2017-09-14 00:00:13 +00:00
default :
assert ( false ) ;
break ;
}
}
2017-10-03 14:41:32 +00:00
void View : : ProcessZoneBegin ( const QueueZoneBegin & ev )
2017-09-14 00:00:13 +00:00
{
2017-11-16 01:19:52 +00:00
auto zone = m_slab . AllocInit < ZoneEvent > ( ) ;
2017-09-21 19:57:40 +00:00
2017-09-26 00:28:14 +00:00
CheckSourceLocation ( ev . srcloc ) ;
2017-09-25 22:13:24 +00:00
zone - > start = ev . time * m_timerMul ;
2017-10-03 13:53:49 +00:00
zone - > end = - 1 ;
2017-10-28 20:14:01 +00:00
zone - > srcloc = ShrinkSourceLocation ( ev . srcloc ) ;
2017-10-10 21:21:30 +00:00
assert ( ev . cpu = = 0xFFFFFFFF | | ev . cpu < = std : : numeric_limits < int8_t > : : max ( ) ) ;
zone - > cpu_start = ev . cpu = = 0xFFFFFFFF ? - 1 : ( int8_t ) ev . cpu ;
2017-09-21 19:57:40 +00:00
2017-12-09 19:05:34 +00:00
m_lastTime = std : : max ( m_lastTime , zone - > start ) ;
2017-10-03 13:53:49 +00:00
NewZone ( zone , ev . thread ) ;
2017-09-14 00:00:13 +00:00
}
2017-11-05 14:04:55 +00:00
void View : : ProcessZoneBeginAllocSrcLoc ( const QueueZoneBegin & ev )
{
2017-11-11 14:59:30 +00:00
auto it = m_pendingSourceLocationPayload . find ( ev . srcloc ) ;
assert ( it ! = m_pendingSourceLocationPayload . end ( ) ) ;
2017-11-16 01:19:52 +00:00
auto zone = m_slab . AllocInit < ZoneEvent > ( ) ;
2017-11-05 14:04:55 +00:00
zone - > start = ev . time * m_timerMul ;
zone - > end = - 1 ;
2017-11-19 18:13:43 +00:00
zone - > srcloc = it - > second ;
2017-11-05 14:04:55 +00:00
assert ( ev . cpu = = 0xFFFFFFFF | | ev . cpu < = std : : numeric_limits < int8_t > : : max ( ) ) ;
zone - > cpu_start = ev . cpu = = 0xFFFFFFFF ? - 1 : ( int8_t ) ev . cpu ;
2017-11-05 15:46:00 +00:00
2017-12-09 19:05:34 +00:00
m_lastTime = std : : max ( m_lastTime , zone - > start ) ;
2017-11-05 14:04:55 +00:00
NewZone ( zone , ev . thread ) ;
2017-11-11 14:59:30 +00:00
m_pendingSourceLocationPayload . erase ( it ) ;
2017-11-05 14:04:55 +00:00
}
2017-10-03 14:41:32 +00:00
void View : : ProcessZoneEnd ( const QueueZoneEnd & ev )
2017-09-14 00:00:13 +00:00
{
2017-11-19 00:16:21 +00:00
auto tit = m_threadMap . find ( ev . thread ) ;
assert ( tit ! = m_threadMap . end ( ) ) ;
2017-11-19 15:27:23 +00:00
auto td = tit - > second ;
2017-11-19 00:16:21 +00:00
auto & stack = td - > stack ;
2017-10-03 14:41:32 +00:00
assert ( ! stack . empty ( ) ) ;
2017-11-19 18:17:54 +00:00
auto zone = stack . back_and_pop ( ) ;
2017-10-03 13:53:49 +00:00
assert ( zone - > end = = - 1 ) ;
zone - > end = ev . time * m_timerMul ;
2017-10-10 21:21:30 +00:00
assert ( ev . cpu = = 0xFFFFFFFF | | ev . cpu < = std : : numeric_limits < int8_t > : : max ( ) ) ;
zone - > cpu_end = ev . cpu = = 0xFFFFFFFF ? - 1 : ( int8_t ) ev . cpu ;
2017-10-03 13:53:49 +00:00
assert ( zone - > end > = zone - > start ) ;
2017-12-09 19:05:34 +00:00
m_lastTime = std : : max ( m_lastTime , zone - > end ) ;
2017-09-13 21:40:28 +00:00
}
2017-10-03 14:41:32 +00:00
void View : : ProcessFrameMark ( const QueueFrameMark & ev )
2017-09-15 22:40:51 +00:00
{
assert ( ! m_frames . empty ( ) ) ;
const auto lastframe = m_frames . back ( ) ;
2017-12-09 19:05:34 +00:00
const auto time = int64_t ( ev . time * m_timerMul ) ;
2017-10-03 13:53:49 +00:00
assert ( lastframe < time ) ;
2017-11-20 01:14:18 +00:00
m_frames . push_back_non_empty ( time ) ;
2017-12-09 19:05:34 +00:00
m_lastTime = std : : max ( m_lastTime , time ) ;
2017-09-15 22:40:51 +00:00
}
2017-10-03 14:41:32 +00:00
void View : : ProcessZoneText ( const QueueZoneText & ev )
2017-09-27 00:18:17 +00:00
{
2017-11-19 00:16:21 +00:00
auto tit = m_threadMap . find ( ev . thread ) ;
assert ( tit ! = m_threadMap . end ( ) ) ;
2017-11-19 15:27:23 +00:00
auto td = tit - > second ;
2017-11-19 00:16:21 +00:00
auto & stack = td - > stack ;
2017-10-03 14:41:32 +00:00
assert ( ! stack . empty ( ) ) ;
auto zone = stack . back ( ) ;
2017-11-11 14:22:55 +00:00
auto it = m_pendingCustomStrings . find ( ev . text ) ;
assert ( it ! = m_pendingCustomStrings . end ( ) ) ;
2017-11-14 22:37:44 +00:00
zone - > text = StringIdx ( it - > second . idx ) ;
2017-11-11 14:22:55 +00:00
m_pendingCustomStrings . erase ( it ) ;
2017-09-27 00:18:17 +00:00
}
2017-12-10 20:37:39 +00:00
void View : : ProcessLockAnnounce ( const QueueLockAnnounce & ev )
{
auto it = m_lockMap . find ( ev . id ) ;
if ( it = = m_lockMap . end ( ) )
{
LockMap lm ;
lm . srcloc = ShrinkSourceLocation ( ev . lckloc ) ;
lm . type = ev . type ;
lm . visible = true ;
lm . valid = true ;
m_lockMap . emplace ( ev . id , std : : move ( lm ) ) ;
}
else
{
it - > second . srcloc = ShrinkSourceLocation ( ev . lckloc ) ;
2017-12-17 17:44:31 +00:00
assert ( it - > second . type = = ev . type ) ;
2017-12-10 20:37:39 +00:00
it - > second . visible = true ;
it - > second . valid = true ;
}
CheckSourceLocation ( ev . lckloc ) ;
}
2017-10-04 16:32:22 +00:00
void View : : ProcessLockWait ( const QueueLockWait & ev )
{
2017-10-12 18:14:17 +00:00
auto it = m_lockMap . find ( ev . id ) ;
if ( it = = m_lockMap . end ( ) )
{
2017-10-22 11:25:58 +00:00
LockMap lm ;
2017-12-10 20:37:39 +00:00
lm . valid = false ;
2017-12-17 17:44:31 +00:00
lm . type = ev . type ;
2017-10-22 11:25:58 +00:00
it = m_lockMap . emplace ( ev . id , std : : move ( lm ) ) . first ;
2017-10-12 18:14:17 +00:00
}
2017-12-10 20:37:39 +00:00
2017-12-17 17:44:31 +00:00
auto lev = ev . type = = LockType : : Lockable ? m_slab . Alloc < LockEvent > ( ) : m_slab . Alloc < LockEventShared > ( ) ;
lev - > time = ev . time * m_timerMul ;
lev - > type = LockEvent : : Type : : Wait ;
lev - > srcloc = 0 ;
2017-10-12 18:14:17 +00:00
InsertLockEvent ( it - > second , lev , ev . thread ) ;
2017-10-04 16:32:22 +00:00
}
void View : : ProcessLockObtain ( const QueueLockObtain & ev )
{
2017-12-17 17:44:31 +00:00
assert ( m_lockMap . find ( ev . id ) ! = m_lockMap . end ( ) ) ;
auto & lock = m_lockMap [ ev . id ] ;
auto lev = lock . type = = LockType : : Lockable ? m_slab . Alloc < LockEvent > ( ) : m_slab . Alloc < LockEventShared > ( ) ;
2017-10-04 17:24:06 +00:00
lev - > time = ev . time * m_timerMul ;
2017-12-10 21:37:56 +00:00
lev - > type = LockEvent : : Type : : Obtain ;
2017-10-06 16:04:17 +00:00
lev - > srcloc = 0 ;
2017-10-04 16:51:50 +00:00
2017-12-17 17:44:31 +00:00
InsertLockEvent ( lock , lev , ev . thread ) ;
2017-10-04 16:32:22 +00:00
}
void View : : ProcessLockRelease ( const QueueLockRelease & ev )
{
2017-12-17 17:44:31 +00:00
assert ( m_lockMap . find ( ev . id ) ! = m_lockMap . end ( ) ) ;
auto & lock = m_lockMap [ ev . id ] ;
auto lev = lock . type = = LockType : : Lockable ? m_slab . Alloc < LockEvent > ( ) : m_slab . Alloc < LockEventShared > ( ) ;
2017-10-04 17:24:06 +00:00
lev - > time = ev . time * m_timerMul ;
2017-12-10 21:37:56 +00:00
lev - > type = LockEvent : : Type : : Release ;
2017-10-06 16:04:17 +00:00
lev - > srcloc = 0 ;
2017-10-04 16:51:50 +00:00
2017-12-17 17:44:31 +00:00
InsertLockEvent ( lock , lev , ev . thread ) ;
2017-10-04 16:32:22 +00:00
}
2017-12-10 21:04:49 +00:00
void View : : ProcessLockSharedWait ( const QueueLockWait & ev )
{
auto it = m_lockMap . find ( ev . id ) ;
if ( it = = m_lockMap . end ( ) )
{
LockMap lm ;
lm . valid = false ;
2017-12-17 17:44:31 +00:00
lm . type = ev . type ;
2017-12-10 21:04:49 +00:00
it = m_lockMap . emplace ( ev . id , std : : move ( lm ) ) . first ;
}
2017-12-17 17:44:31 +00:00
assert ( ev . type = = LockType : : SharedLockable ) ;
auto lev = m_slab . Alloc < LockEventShared > ( ) ;
lev - > time = ev . time * m_timerMul ;
lev - > type = LockEvent : : Type : : WaitShared ;
lev - > srcloc = 0 ;
2017-12-10 21:04:49 +00:00
InsertLockEvent ( it - > second , lev , ev . thread ) ;
}
void View : : ProcessLockSharedObtain ( const QueueLockObtain & ev )
{
2017-12-17 17:44:31 +00:00
assert ( m_lockMap . find ( ev . id ) ! = m_lockMap . end ( ) ) ;
auto & lock = m_lockMap [ ev . id ] ;
assert ( lock . type = = LockType : : SharedLockable ) ;
auto lev = m_slab . Alloc < LockEventShared > ( ) ;
2017-12-10 21:04:49 +00:00
lev - > time = ev . time * m_timerMul ;
2017-12-10 21:42:39 +00:00
lev - > type = LockEvent : : Type : : ObtainShared ;
2017-12-10 21:04:49 +00:00
lev - > srcloc = 0 ;
2017-12-17 17:44:31 +00:00
InsertLockEvent ( lock , lev , ev . thread ) ;
2017-12-10 21:04:49 +00:00
}
void View : : ProcessLockSharedRelease ( const QueueLockRelease & ev )
{
2017-12-17 17:44:31 +00:00
assert ( m_lockMap . find ( ev . id ) ! = m_lockMap . end ( ) ) ;
auto & lock = m_lockMap [ ev . id ] ;
assert ( lock . type = = LockType : : SharedLockable ) ;
auto lev = m_slab . Alloc < LockEventShared > ( ) ;
2017-12-10 21:04:49 +00:00
lev - > time = ev . time * m_timerMul ;
2017-12-10 21:42:39 +00:00
lev - > type = LockEvent : : Type : : ReleaseShared ;
2017-12-10 21:04:49 +00:00
lev - > srcloc = 0 ;
2017-12-17 17:44:31 +00:00
InsertLockEvent ( lock , lev , ev . thread ) ;
2017-12-10 21:04:49 +00:00
}
2017-10-06 15:05:14 +00:00
void View : : ProcessLockMark ( const QueueLockMark & ev )
{
2017-10-06 16:04:17 +00:00
CheckSourceLocation ( ev . srcloc ) ;
2017-10-08 21:03:38 +00:00
auto lit = m_lockMap . find ( ev . id ) ;
assert ( lit ! = m_lockMap . end ( ) ) ;
auto & lockmap = lit - > second ;
auto tid = lockmap . threadMap . find ( ev . thread ) ;
assert ( tid ! = lockmap . threadMap . end ( ) ) ;
const auto thread = tid - > second ;
auto it = lockmap . timeline . end ( ) ;
2017-10-06 16:04:17 +00:00
for ( ; ; )
{
- - it ;
2017-10-08 21:03:38 +00:00
if ( ( * it ) - > thread = = thread )
2017-10-06 16:04:17 +00:00
{
2017-12-10 21:37:56 +00:00
switch ( ( * it ) - > type )
2017-10-06 16:04:17 +00:00
{
case LockEvent : : Type : : Obtain :
2017-12-10 21:42:39 +00:00
case LockEvent : : Type : : ObtainShared :
2017-10-06 16:04:17 +00:00
case LockEvent : : Type : : Wait :
2017-12-10 21:42:39 +00:00
case LockEvent : : Type : : WaitShared :
2017-10-28 20:14:01 +00:00
( * it ) - > srcloc = ShrinkSourceLocation ( ev . srcloc ) ;
2017-10-06 16:04:17 +00:00
return ;
default :
break ;
}
}
}
2017-10-06 15:05:14 +00:00
}
2017-10-13 01:36:59 +00:00
void View : : ProcessPlotData ( const QueuePlotData & ev )
{
PlotData * plot ;
auto it = m_plotMap . find ( ev . name ) ;
if ( it = = m_plotMap . end ( ) )
{
auto pit = m_pendingPlots . find ( ev . name ) ;
if ( pit = = m_pendingPlots . end ( ) )
{
2017-10-21 10:54:12 +00:00
plot = m_slab . AllocInit < PlotData > ( ) ;
2017-10-13 01:36:59 +00:00
plot - > name = ev . name ;
2017-10-22 11:17:34 +00:00
plot - > showFull = true ;
plot - > visible = true ;
2017-10-13 01:36:59 +00:00
m_pendingPlots . emplace ( ev . name , plot ) ;
ServerQuery ( ServerQueryPlotName , ev . name ) ;
}
else
{
plot = pit - > second ;
}
}
else
{
2017-11-21 01:06:17 +00:00
plot = it - > second ;
2017-10-13 01:36:59 +00:00
}
const auto time = int64_t ( ev . time * m_timerMul ) ;
2017-12-09 19:10:32 +00:00
m_lastTime = std : : max ( m_lastTime , time ) ;
2017-10-13 01:36:59 +00:00
switch ( ev . type )
{
case PlotDataType : : Double :
InsertPlot ( plot , time , ev . data . d ) ;
break ;
case PlotDataType : : Float :
InsertPlot ( plot , time , ( double ) ev . data . f ) ;
break ;
case PlotDataType : : Int :
InsertPlot ( plot , time , ( double ) ev . data . i ) ;
break ;
default :
assert ( false ) ;
break ;
}
}
2017-10-21 10:39:26 +00:00
void View : : ProcessMessage ( const QueueMessage & ev )
2017-10-14 12:28:04 +00:00
{
2017-11-11 14:41:21 +00:00
auto it = m_pendingCustomStrings . find ( ev . text ) ;
assert ( it ! = m_pendingCustomStrings . end ( ) ) ;
auto msg = m_slab . Alloc < MessageData > ( ) ;
msg - > time = int64_t ( ev . time * m_timerMul ) ;
2017-11-26 00:43:08 +00:00
msg - > ref = StringRef ( StringRef : : Type : : Idx , it - > second . idx ) ;
2017-12-09 19:10:32 +00:00
m_lastTime = std : : max ( m_lastTime , msg - > time ) ;
2017-11-11 14:41:21 +00:00
InsertMessageData ( msg , ev . thread ) ;
m_pendingCustomStrings . erase ( it ) ;
2017-10-21 10:39:26 +00:00
}
void View : : ProcessMessageLiteral ( const QueueMessage & ev )
{
CheckString ( ev . text ) ;
2017-10-21 11:01:57 +00:00
auto msg = m_slab . Alloc < MessageData > ( ) ;
2017-10-21 10:39:26 +00:00
msg - > time = int64_t ( ev . time * m_timerMul ) ;
2017-11-26 00:43:08 +00:00
msg - > ref = StringRef ( StringRef : : Type : : Ptr , ev . text ) ;
2017-12-09 19:10:32 +00:00
m_lastTime = std : : max ( m_lastTime , msg - > time ) ;
2017-10-21 10:39:26 +00:00
InsertMessageData ( msg , ev . thread ) ;
2017-10-14 12:28:04 +00:00
}
2017-11-11 18:44:09 +00:00
void View : : ProcessGpuNewContext ( const QueueGpuNewContext & ev )
{
2017-11-18 00:49:44 +00:00
assert ( m_gpuCtxMap . find ( ev . context ) = = m_gpuCtxMap . end ( ) ) ;
2017-11-11 20:09:48 +00:00
auto gpu = m_slab . AllocInit < GpuCtxData > ( ) ;
2017-11-25 12:14:16 +00:00
gpu - > timeDiff = int64_t ( ev . cpuTime * m_timerMul - ev . gpuTime ) ;
2017-11-13 23:48:26 +00:00
gpu - > thread = ev . thread ;
2017-11-17 23:32:15 +00:00
gpu - > accuracyBits = ev . accuracyBits ;
2017-11-18 00:07:28 +00:00
gpu - > count = 0 ;
2017-11-11 21:56:05 +00:00
gpu - > showFull = true ;
2017-11-30 14:31:31 +00:00
gpu - > visible = true ;
2017-11-11 18:44:09 +00:00
m_gpuData . push_back ( gpu ) ;
2017-11-21 01:10:41 +00:00
m_gpuCtxMap . emplace ( ev . context , gpu ) ;
2017-11-11 18:44:09 +00:00
}
2017-11-11 20:09:48 +00:00
void View : : ProcessGpuZoneBegin ( const QueueGpuZoneBegin & ev )
{
2017-11-18 00:49:44 +00:00
auto it = m_gpuCtxMap . find ( ev . context ) ;
assert ( it ! = m_gpuCtxMap . end ( ) ) ;
2017-11-21 01:10:41 +00:00
auto ctx = it - > second ;
2017-11-11 20:09:48 +00:00
CheckSourceLocation ( ev . srcloc ) ;
2017-11-16 01:19:52 +00:00
auto zone = m_slab . AllocInit < GpuEvent > ( ) ;
2017-11-15 21:21:02 +00:00
2017-11-11 21:07:08 +00:00
zone - > cpuStart = ev . cpuTime * m_timerMul ;
2017-11-11 20:09:48 +00:00
zone - > cpuEnd = - 1 ;
zone - > gpuStart = std : : numeric_limits < int64_t > : : max ( ) ;
zone - > gpuEnd = - 1 ;
2017-11-11 21:48:54 +00:00
zone - > srcloc = ShrinkSourceLocation ( ev . srcloc ) ;
2017-11-11 20:09:48 +00:00
2017-12-09 19:10:32 +00:00
m_lastTime = std : : max ( m_lastTime , zone - > cpuStart ) ;
2017-11-11 20:09:48 +00:00
auto timeline = & ctx - > timeline ;
if ( ! ctx - > stack . empty ( ) )
{
timeline = & ctx - > stack . back ( ) - > child ;
}
timeline - > push_back ( zone ) ;
ctx - > stack . push_back ( zone ) ;
ctx - > queue . push_back ( zone ) ;
}
void View : : ProcessGpuZoneEnd ( const QueueGpuZoneEnd & ev )
{
2017-11-18 00:49:44 +00:00
auto it = m_gpuCtxMap . find ( ev . context ) ;
assert ( it ! = m_gpuCtxMap . end ( ) ) ;
2017-11-21 01:10:41 +00:00
auto ctx = it - > second ;
2017-11-11 20:09:48 +00:00
assert ( ! ctx - > stack . empty ( ) ) ;
2017-11-20 01:04:45 +00:00
auto zone = ctx - > stack . back_and_pop ( ) ;
2017-11-11 20:09:48 +00:00
ctx - > queue . push_back ( zone ) ;
2017-11-11 21:07:08 +00:00
zone - > cpuEnd = ev . cpuTime * m_timerMul ;
2017-12-09 19:10:32 +00:00
m_lastTime = std : : max ( m_lastTime , zone - > cpuEnd ) ;
2017-11-11 20:09:48 +00:00
}
2017-11-11 21:08:47 +00:00
void View : : ProcessGpuTime ( const QueueGpuTime & ev )
{
2017-11-18 00:49:44 +00:00
auto it = m_gpuCtxMap . find ( ev . context ) ;
assert ( it ! = m_gpuCtxMap . end ( ) ) ;
2017-11-21 01:10:41 +00:00
auto ctx = it - > second ;
2017-11-11 21:08:47 +00:00
auto zone = ctx - > queue . front ( ) ;
if ( zone - > gpuStart = = std : : numeric_limits < int64_t > : : max ( ) )
{
zone - > gpuStart = ctx - > timeDiff + ev . gpuTime ;
2017-12-09 19:10:32 +00:00
m_lastTime = std : : max ( m_lastTime , zone - > gpuStart ) ;
2017-11-18 00:07:28 +00:00
ctx - > count + + ;
2017-11-11 21:08:47 +00:00
}
else
{
zone - > gpuEnd = ctx - > timeDiff + ev . gpuTime ;
2017-12-09 19:10:32 +00:00
m_lastTime = std : : max ( m_lastTime , zone - > gpuEnd ) ;
2017-11-11 21:08:47 +00:00
}
ctx - > queue . erase ( ctx - > queue . begin ( ) ) ;
2017-11-25 12:33:57 +00:00
if ( ! ctx - > resync . empty ( ) )
{
auto & resync = ctx - > resync . front ( ) ;
assert ( resync . events > 0 ) ;
resync . events - - ;
if ( resync . events = = 0 )
{
ctx - > timeDiff = resync . timeDiff ;
ctx - > resync . erase ( ctx - > resync . begin ( ) ) ;
}
}
}
void View : : ProcessGpuResync ( const QueueGpuResync & ev )
{
auto it = m_gpuCtxMap . find ( ev . context ) ;
assert ( it ! = m_gpuCtxMap . end ( ) ) ;
auto ctx = it - > second ;
const auto timeDiff = int64_t ( ev . cpuTime * m_timerMul - ev . gpuTime ) ;
if ( ctx - > queue . empty ( ) )
{
assert ( ctx - > resync . empty ( ) ) ;
ctx - > timeDiff = timeDiff ;
}
else
{
if ( ctx - > resync . empty ( ) )
{
ctx - > resync . push_back ( { timeDiff , uint16_t ( ctx - > queue . size ( ) ) } ) ;
}
else
{
const auto last = ctx - > resync . back ( ) . events ;
ctx - > resync . push_back ( { timeDiff , uint16_t ( ctx - > queue . size ( ) - last ) } ) ;
}
}
2017-11-11 21:08:47 +00:00
}
2017-09-14 00:16:51 +00:00
void View : : CheckString ( uint64_t ptr )
{
2017-11-14 22:06:45 +00:00
if ( ptr = = 0 ) return ;
2017-09-14 00:16:51 +00:00
if ( m_strings . find ( ptr ) ! = m_strings . end ( ) ) return ;
2017-11-23 23:45:55 +00:00
m_strings . emplace ( ptr , " ??? " ) ;
m_pendingStrings + + ;
2017-09-21 23:54:04 +00:00
2017-09-27 00:44:16 +00:00
ServerQuery ( ServerQueryString , ptr ) ;
2017-09-14 00:16:51 +00:00
}
2017-09-21 23:30:57 +00:00
void View : : CheckThreadString ( uint64_t id )
{
if ( m_threadNames . find ( id ) ! = m_threadNames . end ( ) ) return ;
2017-11-23 23:45:55 +00:00
m_threadNames . emplace ( id , " ??? " ) ;
m_pendingThreads + + ;
2017-09-21 23:55:02 +00:00
2017-09-27 00:44:16 +00:00
ServerQuery ( ServerQueryThreadString , id ) ;
2017-09-21 23:30:57 +00:00
}
2017-11-23 23:53:04 +00:00
static const SourceLocation emptySourceLocation = { } ;
2017-09-26 00:28:14 +00:00
void View : : CheckSourceLocation ( uint64_t ptr )
{
2017-11-24 00:05:42 +00:00
if ( m_sourceLocation . find ( ptr ) ! = m_sourceLocation . end ( ) )
{
return ;
}
else
{
NewSourceLocation ( ptr ) ;
}
}
2017-09-26 00:28:14 +00:00
2017-11-24 00:05:42 +00:00
void View : : NewSourceLocation ( uint64_t ptr )
{
2017-11-23 23:53:04 +00:00
m_sourceLocation . emplace ( ptr , emptySourceLocation ) ;
m_pendingSourceLocation + + ;
2017-11-14 22:06:45 +00:00
m_sourceLocationQueue . push_back ( ptr ) ;
2017-09-26 00:28:14 +00:00
2017-09-27 00:44:16 +00:00
ServerQuery ( ServerQuerySourceLocation , ptr ) ;
2017-09-26 00:28:14 +00:00
}
2017-11-10 18:30:04 +00:00
void View : : AddString ( uint64_t ptr , char * str , size_t sz )
2017-09-14 17:43:40 +00:00
{
2017-11-23 23:45:55 +00:00
assert ( m_pendingStrings > 0 ) ;
m_pendingStrings - - ;
auto it = m_strings . find ( ptr ) ;
assert ( it ! = m_strings . end ( ) & & strcmp ( it - > second , " ??? " ) = = 0 ) ;
2017-11-10 18:30:04 +00:00
const auto sl = StoreString ( str , sz ) ;
2017-11-23 23:45:55 +00:00
it - > second = sl . ptr ;
2017-09-14 17:43:40 +00:00
}
2017-11-10 18:24:12 +00:00
void View : : AddThreadString ( uint64_t id , char * str , size_t sz )
2017-09-21 23:30:57 +00:00
{
2017-11-23 23:45:55 +00:00
assert ( m_pendingThreads > 0 ) ;
m_pendingThreads - - ;
auto it = m_threadNames . find ( id ) ;
assert ( it ! = m_threadNames . end ( ) & & strcmp ( it - > second , " ??? " ) = = 0 ) ;
2017-11-10 18:24:12 +00:00
const auto sl = StoreString ( str , sz ) ;
2017-11-23 23:45:55 +00:00
it - > second = sl . ptr ;
2017-09-21 23:30:57 +00:00
}
2017-11-10 18:15:00 +00:00
void View : : AddCustomString ( uint64_t ptr , char * str , size_t sz )
2017-09-27 00:18:17 +00:00
{
2017-11-11 18:01:31 +00:00
assert ( m_pendingCustomStrings . find ( ptr ) = = m_pendingCustomStrings . end ( ) ) ;
2017-11-11 14:41:21 +00:00
m_pendingCustomStrings . emplace ( ptr , StoreString ( str , sz ) ) ;
2017-11-10 16:45:19 +00:00
}
2017-11-11 18:21:07 +00:00
StringLocation View : : StoreString ( char * str , size_t sz )
2017-11-10 16:45:19 +00:00
{
StringLocation ret ;
2017-11-10 18:15:00 +00:00
const char backup = str [ sz ] ;
str [ sz ] = ' \0 ' ;
auto sit = m_stringMap . find ( str ) ;
2017-11-10 16:45:19 +00:00
if ( sit = = m_stringMap . end ( ) )
2017-09-27 00:18:17 +00:00
{
2017-10-21 11:01:57 +00:00
auto ptr = m_slab . Alloc < char > ( sz + 1 ) ;
2017-11-10 18:15:00 +00:00
memcpy ( ptr , str , sz + 1 ) ;
2017-11-10 16:45:19 +00:00
ret . ptr = ptr ;
ret . idx = m_stringData . size ( ) ;
m_stringMap . emplace ( ptr , m_stringData . size ( ) ) ;
m_stringData . push_back ( ptr ) ;
2017-09-27 00:18:17 +00:00
}
else
{
2017-11-10 16:45:19 +00:00
ret . ptr = sit - > first ;
ret . idx = sit - > second ;
2017-09-27 00:18:17 +00:00
}
2017-11-10 18:15:00 +00:00
str [ sz ] = backup ;
2017-11-10 16:45:19 +00:00
return ret ;
2017-09-27 00:18:17 +00:00
}
2017-10-03 14:41:32 +00:00
void View : : AddSourceLocation ( const QueueSourceLocation & srcloc )
2017-09-26 00:28:14 +00:00
{
2017-11-23 23:53:04 +00:00
assert ( m_pendingSourceLocation > 0 ) ;
m_pendingSourceLocation - - ;
2017-11-14 22:06:45 +00:00
const auto ptr = m_sourceLocationQueue . front ( ) ;
m_sourceLocationQueue . erase ( m_sourceLocationQueue . begin ( ) ) ;
2017-11-23 23:53:04 +00:00
auto it = m_sourceLocation . find ( ptr ) ;
assert ( it ! = m_sourceLocation . end ( ) ) ;
2017-11-14 22:06:45 +00:00
CheckString ( srcloc . name ) ;
2017-09-26 00:28:14 +00:00
CheckString ( srcloc . file ) ;
CheckString ( srcloc . function ) ;
2017-11-05 19:54:49 +00:00
uint32_t color = ( srcloc . r < < 16 ) | ( srcloc . g < < 8 ) | srcloc . b ;
2017-11-23 23:53:04 +00:00
it - > second = SourceLocation { srcloc . name = = 0 ? StringRef ( ) : StringRef ( StringRef : : Ptr , srcloc . name ) , StringRef ( StringRef : : Ptr , srcloc . function ) , StringRef ( StringRef : : Ptr , srcloc . file ) , srcloc . line , color } ;
2017-09-26 00:28:14 +00:00
}
2017-09-21 23:30:57 +00:00
2017-11-11 01:02:47 +00:00
void View : : AddSourceLocationPayload ( uint64_t ptr , char * data , size_t sz )
2017-11-05 15:46:00 +00:00
{
const auto start = data ;
2017-11-11 14:59:30 +00:00
assert ( m_pendingSourceLocationPayload . find ( ptr ) = = m_pendingSourceLocationPayload . end ( ) ) ;
2017-11-05 15:46:00 +00:00
uint32_t color , line ;
memcpy ( & color , data , 4 ) ;
memcpy ( & line , data + 4 , 4 ) ;
data + = 8 ;
auto end = data ;
2017-11-11 01:02:47 +00:00
2017-11-14 22:54:52 +00:00
while ( * end ) end + + ;
2017-11-11 01:02:47 +00:00
const auto func = StoreString ( data , end - data ) ;
2017-11-05 15:46:00 +00:00
end + + ;
2017-11-14 22:54:52 +00:00
data = end ;
while ( * end ) end + + ;
const auto source = StoreString ( data , end - data ) ;
end + + ;
const auto nsz = sz - ( end - start ) ;
2017-11-25 14:29:18 +00:00
color = ( ( color & 0x00FF0000 ) > > 16 ) |
( ( color & 0x0000FF00 ) ) |
( ( color & 0x000000FF ) < < 16 ) ;
2017-11-14 22:54:52 +00:00
SourceLocation srcloc { nsz = = 0 ? StringRef ( ) : StringRef ( StringRef : : Idx , StoreString ( end , nsz ) . idx ) , StringRef ( StringRef : : Idx , func . idx ) , StringRef ( StringRef : : Idx , source . idx ) , line , color } ;
2017-11-11 01:31:51 +00:00
auto it = m_sourceLocationPayloadMap . find ( & srcloc ) ;
if ( it = = m_sourceLocationPayloadMap . end ( ) )
{
auto slptr = m_slab . Alloc < SourceLocation > ( ) ;
memcpy ( slptr , & srcloc , sizeof ( srcloc ) ) ;
uint32_t idx = m_sourceLocationPayload . size ( ) ;
m_sourceLocationPayloadMap . emplace ( slptr , idx ) ;
2017-11-11 14:59:30 +00:00
m_pendingSourceLocationPayload . emplace ( ptr , - int32_t ( idx + 1 ) ) ;
2017-11-11 01:31:51 +00:00
m_sourceLocationPayload . push_back ( slptr ) ;
}
else
{
2017-11-11 14:59:30 +00:00
m_pendingSourceLocationPayload . emplace ( ptr , - int32_t ( it - > second + 1 ) ) ;
2017-11-11 01:31:51 +00:00
}
2017-11-05 15:46:00 +00:00
}
2017-10-28 20:14:01 +00:00
uint32_t View : : ShrinkSourceLocation ( uint64_t srcloc )
{
auto it = m_sourceLocationShrink . find ( srcloc ) ;
if ( it ! = m_sourceLocationShrink . end ( ) )
{
return it - > second ;
}
else
{
2017-11-19 16:58:56 +00:00
return NewShrinkedSourceLocation ( srcloc ) ;
2017-10-28 20:14:01 +00:00
}
}
2017-11-19 16:58:56 +00:00
uint32_t View : : NewShrinkedSourceLocation ( uint64_t srcloc )
{
const auto sz = m_sourceLocationExpand . size ( ) ;
m_sourceLocationExpand . push_back ( srcloc ) ;
m_sourceLocationShrink . emplace ( srcloc , sz ) ;
return sz ;
}
2017-10-21 10:39:26 +00:00
void View : : InsertMessageData ( MessageData * msg , uint64_t thread )
{
2017-11-20 01:14:18 +00:00
if ( m_messages . empty ( ) )
2017-10-14 12:28:04 +00:00
{
2017-10-21 10:39:26 +00:00
m_messages . push_back ( msg ) ;
2017-10-14 12:28:04 +00:00
}
2017-11-20 01:14:18 +00:00
else if ( m_messages . back ( ) - > time < msg - > time )
{
m_messages . push_back_non_empty ( msg ) ;
}
2017-10-14 12:28:04 +00:00
else
{
2017-10-21 10:39:26 +00:00
auto mit = std : : lower_bound ( m_messages . begin ( ) , m_messages . end ( ) , msg - > time , [ ] ( const auto & lhs , const auto & rhs ) { return lhs - > time < rhs ; } ) ;
m_messages . insert ( mit , msg ) ;
2017-10-14 12:46:03 +00:00
}
2017-11-20 01:14:18 +00:00
auto vec = & NoticeThread ( thread ) - > messages ;
if ( vec - > empty ( ) )
2017-10-14 12:46:03 +00:00
{
2017-10-21 10:39:26 +00:00
vec - > push_back ( msg ) ;
2017-10-14 12:46:03 +00:00
}
2017-11-20 01:14:18 +00:00
else if ( vec - > back ( ) - > time < msg - > time )
{
vec - > push_back_non_empty ( msg ) ;
}
2017-10-14 12:46:03 +00:00
else
{
2017-10-21 10:39:26 +00:00
auto tmit = std : : lower_bound ( vec - > begin ( ) , vec - > end ( ) , msg - > time , [ ] ( const auto & lhs , const auto & rhs ) { return lhs - > time < rhs ; } ) ;
vec - > insert ( tmit , msg ) ;
2017-10-14 12:46:03 +00:00
}
2017-10-14 12:28:04 +00:00
}
2017-11-11 18:21:07 +00:00
ThreadData * View : : NoticeThread ( uint64_t thread )
2017-09-14 19:05:01 +00:00
{
2017-09-21 23:15:58 +00:00
auto it = m_threadMap . find ( thread ) ;
2017-11-19 16:58:56 +00:00
if ( it ! = m_threadMap . end ( ) )
2017-09-14 19:28:40 +00:00
{
2017-11-19 16:58:56 +00:00
return it - > second ;
2017-09-21 23:15:58 +00:00
}
else
{
2017-11-19 16:58:56 +00:00
return NewThread ( thread ) ;
2017-09-21 23:15:58 +00:00
}
2017-10-21 11:14:20 +00:00
}
2017-09-21 23:15:58 +00:00
2017-11-19 16:58:56 +00:00
ThreadData * View : : NewThread ( uint64_t thread )
{
CheckThreadString ( thread ) ;
auto td = m_slab . AllocInit < ThreadData > ( ) ;
td - > id = thread ;
td - > count = 0 ;
td - > showFull = true ;
td - > visible = true ;
m_threads . push_back ( td ) ;
m_threadMap . emplace ( thread , td ) ;
return td ;
}
2017-10-22 13:37:24 +00:00
void View : : NewZone ( ZoneEvent * zone , uint64_t thread )
2017-10-21 11:14:20 +00:00
{
m_zonesCnt + + ;
2017-11-18 00:14:16 +00:00
auto td = NoticeThread ( thread ) ;
td - > count + + ;
2017-11-19 00:16:21 +00:00
if ( td - > stack . empty ( ) )
2017-09-21 23:15:58 +00:00
{
2017-11-19 00:16:21 +00:00
td - > stack . push_back ( zone ) ;
td - > timeline . push_back ( zone ) ;
2017-09-14 19:28:40 +00:00
}
else
{
2017-11-19 00:16:21 +00:00
td - > stack . back ( ) - > child . push_back ( zone ) ;
2017-11-19 16:28:12 +00:00
td - > stack . push_back_non_empty ( zone ) ;
2017-09-14 19:28:40 +00:00
}
2017-09-14 19:05:01 +00:00
}
2017-12-17 17:44:31 +00:00
static void UpdateLockCountLockable ( LockMap & lockmap , size_t pos )
2017-10-04 16:51:50 +00:00
{
2017-10-04 17:57:06 +00:00
auto & timeline = lockmap . timeline ;
2017-12-17 17:44:31 +00:00
uint8_t lockingThread ;
uint8_t lockCount ;
uint64_t waitList ;
if ( pos = = 0 )
2017-10-04 17:24:24 +00:00
{
2017-12-17 17:44:31 +00:00
lockingThread = 0 ;
lockCount = 0 ;
waitList = 0 ;
2017-10-04 17:24:24 +00:00
}
2017-12-17 17:44:31 +00:00
else
2017-11-20 01:14:18 +00:00
{
2017-12-17 17:44:31 +00:00
const auto tl = timeline [ pos - 1 ] ;
lockingThread = tl - > lockingThread ;
lockCount = tl - > lockCount ;
waitList = tl - > waitList ;
2017-11-20 01:14:18 +00:00
}
2017-12-17 17:44:31 +00:00
const auto end = timeline . size ( ) ;
while ( pos ! = end )
2017-10-04 17:24:24 +00:00
{
2017-12-17 17:44:31 +00:00
const auto tl = timeline [ pos ] ;
const auto tbit = uint64_t ( 1 ) < < tl - > thread ;
switch ( ( LockEvent : : Type ) tl - > type )
{
case LockEvent : : Type : : Wait :
waitList | = tbit ;
break ;
case LockEvent : : Type : : Obtain :
assert ( lockCount < std : : numeric_limits < uint8_t > : : max ( ) ) ;
assert ( ( waitList & tbit ) ! = 0 ) ;
waitList & = ~ tbit ;
lockingThread = tl - > thread ;
lockCount + + ;
break ;
case LockEvent : : Type : : Release :
assert ( lockCount > 0 ) ;
lockCount - - ;
break ;
default :
break ;
}
tl - > lockingThread = lockingThread ;
tl - > waitList = waitList ;
tl - > lockCount = lockCount ;
assert ( tl - > lockingThread = = lockingThread ) ;
pos + + ;
2017-10-04 17:42:44 +00:00
}
}
2017-12-17 17:44:31 +00:00
static void UpdateLockCountSharedLockable ( LockMap & lockmap , size_t pos )
2017-10-04 17:42:44 +00:00
{
2017-10-08 21:03:38 +00:00
auto & timeline = lockmap . timeline ;
2017-11-19 18:35:16 +00:00
uint8_t lockingThread ;
uint8_t lockCount ;
2017-12-10 22:30:13 +00:00
uint64_t waitShared ;
2017-11-19 18:35:16 +00:00
uint64_t waitList ;
2017-12-10 21:42:39 +00:00
uint64_t sharedList ;
2017-11-19 18:35:16 +00:00
if ( pos = = 0 )
{
lockingThread = 0 ;
lockCount = 0 ;
2017-12-10 22:30:13 +00:00
waitShared = 0 ;
2017-11-19 18:35:16 +00:00
waitList = 0 ;
2017-12-10 21:42:39 +00:00
sharedList = 0 ;
2017-11-19 18:35:16 +00:00
}
else
{
2017-12-17 17:44:31 +00:00
const auto tl = ( LockEventShared * ) timeline [ pos - 1 ] ;
2017-11-19 18:35:16 +00:00
lockingThread = tl - > lockingThread ;
lockCount = tl - > lockCount ;
2017-12-10 22:30:13 +00:00
waitShared = tl - > waitShared ;
2017-11-19 18:35:16 +00:00
waitList = tl - > waitList ;
2017-12-10 21:42:39 +00:00
sharedList = tl - > sharedList ;
2017-11-19 18:35:16 +00:00
}
2017-10-04 17:42:44 +00:00
const auto end = timeline . size ( ) ;
2017-12-10 21:42:39 +00:00
// ObtainShared and ReleaseShared should assert on lockCount == 0, but
// due to the async retrieval of data from threads that not possible.
2017-10-04 17:42:44 +00:00
while ( pos ! = end )
{
2017-12-17 17:44:31 +00:00
const auto tl = ( LockEventShared * ) timeline [ pos ] ;
2017-11-19 18:35:16 +00:00
const auto tbit = uint64_t ( 1 ) < < tl - > thread ;
switch ( ( LockEvent : : Type ) tl - > type )
2017-10-04 17:42:44 +00:00
{
2017-10-05 12:02:08 +00:00
case LockEvent : : Type : : Wait :
2017-10-08 21:03:38 +00:00
waitList | = tbit ;
2017-10-05 12:02:08 +00:00
break ;
2017-12-10 22:30:13 +00:00
case LockEvent : : Type : : WaitShared :
waitShared | = tbit ;
break ;
2017-10-04 17:42:44 +00:00
case LockEvent : : Type : : Obtain :
2017-10-05 12:02:08 +00:00
assert ( lockCount < std : : numeric_limits < uint8_t > : : max ( ) ) ;
2017-12-10 21:42:25 +00:00
assert ( ( waitList & tbit ) ! = 0 ) ;
2017-10-08 21:03:38 +00:00
waitList & = ~ tbit ;
2017-11-19 18:35:16 +00:00
lockingThread = tl - > thread ;
2017-10-05 12:02:08 +00:00
lockCount + + ;
2017-10-04 17:42:44 +00:00
break ;
case LockEvent : : Type : : Release :
2017-10-05 12:02:08 +00:00
assert ( lockCount > 0 ) ;
lockCount - - ;
2017-10-04 17:42:44 +00:00
break ;
2017-12-10 21:42:39 +00:00
case LockEvent : : Type : : ObtainShared :
2017-12-10 22:30:13 +00:00
assert ( ( waitShared & tbit ) ! = 0 ) ;
2017-12-10 21:42:39 +00:00
assert ( ( sharedList & tbit ) = = 0 ) ;
2017-12-10 22:30:13 +00:00
waitShared & = ~ tbit ;
2017-12-10 21:42:39 +00:00
sharedList | = tbit ;
break ;
case LockEvent : : Type : : ReleaseShared :
assert ( ( sharedList & tbit ) ! = 0 ) ;
sharedList & = ~ tbit ;
break ;
2017-10-04 17:42:44 +00:00
default :
break ;
}
2017-11-19 18:35:16 +00:00
tl - > lockingThread = lockingThread ;
2017-12-10 22:30:13 +00:00
tl - > waitShared = waitShared ;
2017-11-19 18:35:16 +00:00
tl - > waitList = waitList ;
2017-12-10 21:42:39 +00:00
tl - > sharedList = sharedList ;
2017-11-19 18:35:16 +00:00
tl - > lockCount = lockCount ;
assert ( tl - > lockingThread = = lockingThread ) ;
2017-10-04 17:42:44 +00:00
pos + + ;
2017-10-04 17:24:24 +00:00
}
2017-10-04 16:51:50 +00:00
}
2017-12-17 17:44:31 +00:00
static inline void UpdateLockCount ( LockMap & lockmap , size_t pos )
{
if ( lockmap . type = = LockType : : Lockable )
{
UpdateLockCountLockable ( lockmap , pos ) ;
}
else
{
UpdateLockCountSharedLockable ( lockmap , pos ) ;
}
}
void View : : InsertLockEvent ( LockMap & lockmap , LockEvent * lev , uint64_t thread )
{
m_lastTime = std : : max ( m_lastTime , lev - > time ) ;
NoticeThread ( thread ) ;
auto it = lockmap . threadMap . find ( thread ) ;
if ( it = = lockmap . threadMap . end ( ) )
{
assert ( lockmap . threadList . size ( ) < MaxLockThreads ) ;
it = lockmap . threadMap . emplace ( thread , lockmap . threadList . size ( ) ) . first ;
lockmap . threadList . emplace_back ( thread ) ;
}
lev - > thread = it - > second ;
assert ( lev - > thread = = it - > second ) ;
auto & timeline = lockmap . timeline ;
if ( timeline . empty ( ) )
{
timeline . push_back ( lev ) ;
UpdateLockCount ( lockmap , timeline . size ( ) - 1 ) ;
}
else if ( timeline . back ( ) - > time < lev - > time )
{
timeline . push_back_non_empty ( lev ) ;
UpdateLockCount ( lockmap , timeline . size ( ) - 1 ) ;
}
else
{
auto it = std : : lower_bound ( timeline . begin ( ) , timeline . end ( ) , lev - > time , [ ] ( const auto & lhs , const auto & rhs ) { return lhs - > time < rhs ; } ) ;
it = timeline . insert ( it , lev ) ;
UpdateLockCount ( lockmap , std : : distance ( timeline . begin ( ) , it ) ) ;
}
}
2017-10-13 01:36:59 +00:00
void View : : InsertPlot ( PlotData * plot , int64_t time , double val )
{
2017-11-20 01:14:18 +00:00
if ( plot - > data . empty ( ) )
2017-10-13 01:36:59 +00:00
{
2017-11-20 01:14:18 +00:00
plot - > min = val ;
plot - > max = val ;
2017-12-05 20:24:09 +00:00
plot - > data . push_back ( { time , val } ) ;
2017-10-13 01:36:59 +00:00
}
2017-12-05 20:24:09 +00:00
else if ( plot - > data . back ( ) . time < time )
2017-11-20 01:14:18 +00:00
{
if ( plot - > min > val ) plot - > min = val ;
else if ( plot - > max < val ) plot - > max = val ;
2017-12-05 20:24:09 +00:00
plot - > data . push_back_non_empty ( { time , val } ) ;
2017-11-20 01:14:18 +00:00
}
2017-10-13 01:36:59 +00:00
else
{
2017-10-13 13:32:59 +00:00
if ( plot - > min > val ) plot - > min = val ;
else if ( plot - > max < val ) plot - > max = val ;
2017-11-20 01:14:18 +00:00
if ( plot - > postpone . empty ( ) )
{
plot - > postponeTime = std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( std : : chrono : : high_resolution_clock : : now ( ) . time_since_epoch ( ) ) . count ( ) ;
2017-12-05 20:24:09 +00:00
plot - > postpone . push_back ( { time , val } ) ;
2017-11-20 01:14:18 +00:00
}
else
{
2017-12-05 20:24:09 +00:00
plot - > postpone . push_back_non_empty ( { time , val } ) ;
2017-11-20 01:14:18 +00:00
}
2017-10-13 01:36:59 +00:00
}
}
2017-11-10 18:41:37 +00:00
void View : : HandlePlotName ( uint64_t name , char * str , size_t sz )
2017-10-13 01:36:59 +00:00
{
auto pit = m_pendingPlots . find ( name ) ;
assert ( pit ! = m_pendingPlots . end ( ) ) ;
2017-11-10 18:41:37 +00:00
const auto sl = StoreString ( str , sz ) ;
auto it = m_plotRev . find ( sl . ptr ) ;
2017-10-13 01:36:59 +00:00
if ( it = = m_plotRev . end ( ) )
{
2017-11-21 01:06:17 +00:00
m_plotMap . emplace ( name , pit - > second ) ;
m_plotRev . emplace ( sl . ptr , pit - > second ) ;
2017-10-19 21:10:47 +00:00
m_plots . push_back ( pit - > second ) ;
2017-11-10 18:41:37 +00:00
m_strings . emplace ( name , sl . ptr ) ;
2017-10-13 01:36:59 +00:00
}
else
{
2017-11-21 01:06:17 +00:00
auto plot = it - > second ;
m_plotMap . emplace ( name , plot ) ;
2017-10-13 01:36:59 +00:00
const auto & pp = pit - > second - > data ;
for ( auto & v : pp )
{
2017-12-05 20:24:09 +00:00
InsertPlot ( plot , v . time , v . val ) ;
2017-10-13 01:36:59 +00:00
}
2017-12-05 20:24:09 +00:00
// TODO what happens with the source data here?
2017-10-13 01:36:59 +00:00
}
m_pendingPlots . erase ( pit ) ;
}
2017-10-19 21:26:21 +00:00
void View : : HandlePostponedPlots ( )
{
for ( auto & plot : m_plots )
{
auto & src = plot - > postpone ;
if ( src . empty ( ) ) continue ;
2017-10-21 11:32:51 +00:00
if ( std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( std : : chrono : : high_resolution_clock : : now ( ) . time_since_epoch ( ) ) . count ( ) - plot - > postponeTime < 100 ) continue ;
2017-10-19 21:26:21 +00:00
auto & dst = plot - > data ;
2017-12-05 20:24:09 +00:00
std : : sort ( src . begin ( ) , src . end ( ) , [ ] ( const auto & l , const auto & r ) { return l . time < r . time ; } ) ;
const auto ds = std : : lower_bound ( dst . begin ( ) , dst . end ( ) , src . front ( ) . time , [ ] ( const auto & l , const auto & r ) { return l . time < r ; } ) ;
2017-10-19 21:26:21 +00:00
const auto dsd = std : : distance ( dst . begin ( ) , ds ) ;
2017-12-05 20:24:09 +00:00
const auto de = std : : lower_bound ( ds , dst . end ( ) , src . back ( ) . time , [ ] ( const auto & l , const auto & r ) { return l . time < r ; } ) ;
2017-10-19 21:26:21 +00:00
const auto ded = std : : distance ( dst . begin ( ) , de ) ;
dst . insert ( de , src . begin ( ) , src . end ( ) ) ;
2017-12-05 20:24:09 +00:00
std : : inplace_merge ( dst . begin ( ) + dsd , dst . begin ( ) + ded , dst . begin ( ) + ded + src . size ( ) , [ ] ( const auto & l , const auto & r ) { return l . time < r . time ; } ) ;
2017-10-19 21:26:21 +00:00
src . clear ( ) ;
}
}
2017-10-28 19:50:06 +00:00
int64_t View : : GetFrameTime ( size_t idx ) const
2017-09-18 19:26:22 +00:00
{
if ( idx < m_frames . size ( ) - 1 )
{
return m_frames [ idx + 1 ] - m_frames [ idx ] ;
}
else
{
2017-12-09 19:05:34 +00:00
return m_lastTime = = 0 ? 0 : m_lastTime - m_frames . back ( ) ;
2017-09-18 19:26:22 +00:00
}
}
2017-10-28 19:50:06 +00:00
int64_t View : : GetFrameBegin ( size_t idx ) const
2017-09-20 20:34:56 +00:00
{
assert ( idx < m_frames . size ( ) ) ;
return m_frames [ idx ] ;
}
2017-10-28 19:50:06 +00:00
int64_t View : : GetFrameEnd ( size_t idx ) const
2017-09-20 20:34:56 +00:00
{
if ( idx < m_frames . size ( ) - 1 )
{
return m_frames [ idx + 1 ] ;
}
else
{
2017-12-09 19:05:34 +00:00
return m_lastTime ;
2017-09-18 00:22:59 +00:00
}
}
2017-10-22 13:37:24 +00:00
int64_t View : : GetZoneEnd ( const ZoneEvent & ev ) const
2017-09-23 13:39:39 +00:00
{
2017-09-23 13:41:10 +00:00
auto ptr = & ev ;
for ( ; ; )
{
if ( ptr - > end ! = - 1 ) return ptr - > end ;
if ( ptr - > child . empty ( ) ) return ptr - > start ;
ptr = ptr - > child . back ( ) ;
}
2017-09-23 13:39:39 +00:00
}
2017-11-11 21:56:05 +00:00
int64_t View : : GetZoneEnd ( const GpuEvent & ev ) const
{
auto ptr = & ev ;
for ( ; ; )
{
if ( ptr - > gpuEnd ! = - 1 ) return ptr - > gpuEnd ;
if ( ptr - > child . empty ( ) ) return ptr - > gpuStart ;
ptr = ptr - > child . back ( ) ;
}
}
2017-09-21 00:10:20 +00:00
const char * View : : GetString ( uint64_t ptr ) const
{
const auto it = m_strings . find ( ptr ) ;
2017-11-11 00:39:34 +00:00
if ( it = = m_strings . end ( ) | | it - > second = = nullptr )
2017-09-21 00:10:20 +00:00
{
return " ??? " ;
}
else
{
2017-11-10 18:30:04 +00:00
return it - > second ;
2017-09-21 00:10:20 +00:00
}
}
2017-11-11 00:39:34 +00:00
const char * View : : GetString ( const StringRef & ref ) const
{
2017-11-11 01:02:47 +00:00
if ( ref . isidx )
2017-11-11 00:39:34 +00:00
{
2017-11-14 22:37:20 +00:00
assert ( ref . active ) ;
2017-11-11 01:02:47 +00:00
return m_stringData [ ref . stridx ] ;
2017-11-11 00:39:34 +00:00
}
else
{
2017-11-14 22:37:20 +00:00
if ( ref . active )
{
return GetString ( ref . strptr ) ;
}
else
{
return " ??? " ;
}
2017-11-11 00:39:34 +00:00
}
}
2017-11-14 22:37:44 +00:00
const char * View : : GetString ( const StringIdx & idx ) const
{
assert ( idx . active ) ;
return m_stringData [ idx . idx ] ;
}
2017-09-21 23:30:57 +00:00
const char * View : : GetThreadString ( uint64_t id ) const
{
const auto it = m_threadNames . find ( id ) ;
if ( it = = m_threadNames . end ( ) )
{
return " ??? " ;
}
else
{
2017-11-10 18:24:12 +00:00
return it - > second ;
2017-09-21 23:30:57 +00:00
}
}
2017-11-05 20:24:50 +00:00
const SourceLocation & View : : GetSourceLocation ( int32_t srcloc ) const
2017-09-26 16:54:48 +00:00
{
2017-11-05 20:24:50 +00:00
if ( srcloc < 0 )
{
return * m_sourceLocationPayload [ - srcloc - 1 ] ;
}
else
{
const auto it = m_sourceLocation . find ( m_sourceLocationExpand [ srcloc ] ) ;
2017-11-23 23:53:04 +00:00
assert ( it ! = m_sourceLocation . end ( ) ) ;
2017-11-05 20:24:50 +00:00
return it - > second ;
}
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 + + ;
}
}
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 ( )
{
2017-09-20 18:38:12 +00:00
if ( ! m_hasData . load ( std : : memory_order_acquire ) )
{
ImGui : : Begin ( m_addr . c_str ( ) , nullptr , ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_ShowBorders ) ;
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
2017-11-15 20:49:41 +00:00
std : : lock_guard < NonRecursiveBenaphore > lock ( m_lock ) ;
2017-10-12 21:44:35 +00:00
ImGui : : Begin ( m_captureName . c_str ( ) , nullptr , ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_NoScrollbar ) ;
2017-10-13 11:32:23 +00:00
if ( ImGui : : Button ( m_pause ? " Resume " : " Pause " , ImVec2 ( 70 , 0 ) ) ) m_pause = ! m_pause ;
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " Options " , ImVec2 ( 70 , 0 ) ) ) m_showOptions = true ;
2017-09-30 12:37:21 +00:00
ImGui : : SameLine ( ) ;
2017-10-14 12:36:30 +00:00
if ( ImGui : : Button ( " Messages " , ImVec2 ( 70 , 0 ) ) ) m_showMessages = true ;
ImGui : : SameLine ( ) ;
2017-12-09 19:05:34 +00:00
ImGui : : Text ( " Frames: %-7 " PRIu64 " Time span: %-10s View span: %-10s Zones: %-13s Queue delay: %s Timer resolution: %s " , m_frames . size ( ) , TimeToString ( m_lastTime - m_frames [ 0 ] ) , TimeToString ( m_zvEnd - m_zvStart ) , RealToString ( m_zonesCnt , true ) , TimeToString ( m_delay ) , TimeToString ( m_resolution ) ) ;
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 ( ) ;
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
{
2017-11-15 20:49:41 +00:00
std : : lock_guard < NonRecursiveBenaphore > lock ( m_mbpslock ) ;
2017-11-23 00:23:40 +00:00
ImGui : : Begin ( m_addr . c_str ( ) , nullptr , ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_ShowBorders ) ;
2017-09-15 00:30:22 +00:00
const auto mbps = m_mbps . back ( ) ;
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 ( ) ;
ImGui : : PlotLines ( buf , m_mbps . data ( ) , m_mbps . size ( ) , 0 , nullptr , 0 , std : : numeric_limits < float > : : max ( ) , ImVec2 ( 150 , 0 ) ) ;
2017-11-23 00:23:40 +00:00
ImGui : : Text ( " Ratio %.1f%% Real: %6.2f Mbps " , m_compRatio * 100.f , mbps / m_compRatio ) ;
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 ( ) ;
2017-10-18 21:25:35 +00:00
ImGui : : GetWindowDrawList ( ) - > AddCircleFilled ( wpos + ImVec2 ( 1 + cs * 0.5 , 3 + ty * 0.5 ) , cs * 0.5 , m_connected . load ( std : : memory_order_relaxed ) ? 0xFF2222CC : 0xFF444444 , 10 ) ;
2017-09-17 22:31:38 +00:00
2017-11-15 20:49:41 +00:00
std : : lock_guard < NonRecursiveBenaphore > lock ( m_lock ) ;
2017-09-15 22:57:50 +00:00
{
const auto sz = m_frames . size ( ) ;
if ( sz > 1 )
{
const auto dt = m_frames [ sz - 1 ] - m_frames [ sz - 2 ] ;
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 )
{
Write ( * f ) ;
}
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 ( )
{
2017-09-20 19:21:21 +00:00
assert ( ! m_frames . empty ( ) ) ;
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 ) ;
2017-09-18 00:37:25 +00:00
const int total = m_frames . size ( ) ;
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 ;
2017-09-20 20:41:05 +00:00
m_zvStart = m_frames [ std : : max ( 0 , ( int ) m_frames . size ( ) - 4 ) ] ;
2017-09-23 12:45:38 +00:00
if ( m_frames . size ( ) = = 1 )
{
2017-12-09 19:05:34 +00:00
m_zvEnd = m_lastTime ;
2017-09-23 12:45:38 +00:00
}
else
{
m_zvEnd = m_frames . back ( ) ;
}
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 )
{
2017-10-28 19:50:06 +00:00
auto f = GetFrameTime ( sel ) ;
2017-09-19 19:10:31 +00:00
auto g = std : : min ( group , total - sel ) ;
for ( int j = 1 ; j < g ; j + + )
{
f = std : : max ( f , GetFrameTime ( sel + j ) ) ;
}
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 ( ) ;
2017-10-16 23:17:55 +00:00
ImGui : : Text ( " Time: %s " , TimeToString ( GetFrameTime ( sel ) ) ) ;
}
else
{
ImGui : : Text ( " Frame: %i " , sel ) ;
2017-11-17 23:51:04 +00:00
ImGui : : Separator ( ) ;
2017-10-16 23:17:55 +00:00
ImGui : : Text ( " Frame time: %s " , TimeToString ( GetFrameTime ( sel ) ) ) ;
}
2017-09-19 19:10:31 +00:00
}
2017-09-21 00:30:05 +00:00
ImGui : : Text ( " Time from start of program: %s " , TimeToString ( m_frames [ sel ] - m_frames [ 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 ;
m_zvStart = GetFrameBegin ( sel ) ;
m_zvEnd = GetFrameEnd ( sel + group - 1 ) ;
if ( m_zvStart = = m_zvEnd ) m_zvStart - - ;
}
else if ( ImGui : : IsMouseDragging ( 0 ) )
{
m_zvStart = std : : min ( m_zvStart , ( int64_t ) GetFrameBegin ( sel ) ) ;
m_zvEnd = std : : max ( m_zvEnd , ( int64_t ) GetFrameEnd ( sel + group - 1 ) ) ;
}
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
{
2017-10-28 19:50:06 +00:00
auto f = 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 + + )
{
2017-09-18 22:26:40 +00:00
f = std : : max ( f , 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
2017-09-20 20:35:10 +00:00
const auto zitbegin = std : : lower_bound ( m_frames . begin ( ) , m_frames . end ( ) , m_zvStart ) ;
2017-09-20 23:41:52 +00:00
if ( zitbegin = = m_frames . end ( ) ) return ;
2017-11-21 01:28:46 +00:00
const auto zitend = std : : lower_bound ( zitbegin , m_frames . end ( ) , m_zvEnd ) ;
2017-09-20 19:21:29 +00:00
2017-09-20 23:13:23 +00:00
auto zbegin = ( int ) std : : distance ( m_frames . begin ( ) , zitbegin ) ;
if ( zbegin > 0 & & * zitbegin ! = m_zvStart ) zbegin - - ;
2017-09-20 20:35:10 +00:00
const auto zend = ( int ) std : : distance ( m_frames . begin ( ) , zitend ) ;
2017-09-20 19:21:29 +00:00
if ( zend > m_frameStart & & zbegin < m_frameStart + onScreen * group )
{
auto x0 = std : : max ( 0 , ( zbegin - m_frameStart ) * fwidth / group ) ;
auto x1 = std : : min ( onScreen * fwidth , ( zend - m_frameStart ) * fwidth / group ) ;
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 ) )
{
m_drawRegion = true ;
m_regionEnd = m_regionStart = m_zvStart + ( io . MousePos . x - wpos . x ) * nspx ;
}
else if ( ImGui : : IsMouseDragging ( 0 , 0 ) )
{
m_regionEnd = m_zvStart + ( io . MousePos . x - wpos . x ) * nspx ;
}
else
{
m_drawRegion = false ;
}
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 ] ;
2017-11-26 01:24:13 +00:00
const auto t = m_zvStart - m_frames [ 0 ] ;
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 ;
}
}
2017-10-22 15:48:01 +00:00
const auto zitbegin = std : : lower_bound ( m_frames . begin ( ) , m_frames . end ( ) , m_zvStart ) ;
if ( zitbegin = = m_frames . end ( ) ) return hover ;
2017-11-21 01:28:46 +00:00
const auto zitend = std : : lower_bound ( zitbegin , m_frames . end ( ) , m_zvEnd ) ;
2017-09-20 22:57:26 +00:00
2017-10-22 15:48:01 +00:00
auto zbegin = ( int ) std : : distance ( m_frames . begin ( ) , zitbegin ) ;
if ( zbegin > 0 & & * zitbegin ! = m_zvStart ) zbegin - - ;
const auto zend = ( int ) std : : distance ( m_frames . begin ( ) , zitend ) ;
2017-09-20 22:57:26 +00:00
2017-10-22 15:48:01 +00:00
for ( int i = zbegin ; i < zend ; i + + )
{
const auto ftime = GetFrameTime ( i ) ;
const auto fbegin = ( int64_t ) GetFrameBegin ( i ) ;
const auto fend = ( int64_t ) GetFrameEnd ( i ) ;
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 ( ) ;
2017-10-22 15:48:01 +00:00
ImGui : : Text ( " Time from start of program: %s " , TimeToString ( m_frames [ i ] - m_frames [ 0 ] ) ) ;
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
2017-10-22 15:48:01 +00:00
const auto fend = GetFrameEnd ( zend - 1 ) ;
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 )
{
2017-11-26 01:36:38 +00:00
for ( size_t i = 0 ; i < m_gpuData . size ( ) ; i + + )
2017-11-11 21:56:05 +00:00
{
auto & v = m_gpuData [ i ] ;
2017-11-30 14:31:31 +00:00
if ( ! v - > visible ) continue ;
2017-11-11 21:56:05 +00:00
draw - > AddLine ( wpos + ImVec2 ( 0 , offset + ostep - 1 ) , wpos + ImVec2 ( w , offset + ostep - 1 ) , 0x33FFFFFF ) ;
if ( v - > showFull )
{
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 ] ;
sprintf ( buf , " GPU context %i " , i ) ;
draw - > AddText ( wpos + ImVec2 ( ty , offset ) , v - > showFull ? 0xFFFFAAAA : 0xFF886666 , buf ) ;
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 ) )
{
v - > showFull = ! v - > showFull ;
}
ImGui : : BeginTooltip ( ) ;
ImGui : : Text ( " %s " , buf ) ;
ImGui : : Separator ( ) ;
2017-11-18 00:03:32 +00:00
ImGui : : Text ( " Thread: %s " , 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 ( ) )
{
ImGui : : Text ( " Appeared at %s " , TimeToString ( t - m_frames [ 0 ] ) ) ;
}
}
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 ;
if ( v - > showFull )
{
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 } ;
2017-09-21 23:15:58 +00:00
for ( auto & v : m_threads )
2017-09-21 00:16:01 +00:00
{
2017-10-22 11:13:26 +00:00
if ( ! v - > visible ) continue ;
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
2017-10-22 11:13:26 +00:00
if ( v - > 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
{
ImGui : : Text ( " %s " , TimeToString ( ( * it ) - > time - m_frames [ 0 ] ) ) ;
2017-11-17 23:51:04 +00:00
ImGui : : Separator ( ) ;
ImGui : : Text ( " Message text: " ) ;
ImGui : : TextColored ( ImVec4 ( 0xCC / 255.f , 0xCC / 255.f , 0x22 / 255.f , 1.f ) , " %s " , 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 ) ;
}
const auto txt = 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 ) ;
}
2017-10-22 11:13:26 +00:00
draw - > AddText ( wpos + ImVec2 ( ty , offset ) , v - > 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 ) )
{
v - > showFull = ! v - > showFull ;
}
ImGui : : BeginTooltip ( ) ;
ImGui : : Text ( " %s " , GetThreadString ( v - > id ) ) ;
if ( ! v - > timeline . empty ( ) )
{
2017-11-18 00:14:55 +00:00
ImGui : : Separator ( ) ;
2017-11-18 00:03:40 +00:00
ImGui : : Text ( " Appeared at %s " , TimeToString ( v - > timeline . front ( ) - > start - m_frames [ 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 ;
2017-10-22 11:13:26 +00:00
if ( v - > 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
2017-10-15 14:42:56 +00:00
if ( m_drawRegion & & m_regionStart ! = m_regionEnd )
{
const auto s = std : : min ( m_regionStart , m_regionEnd ) ;
const auto e = std : : max ( m_regionStart , m_regionEnd ) ;
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
{
2017-10-28 20:20:39 +00:00
// cast to uint64_t, so that unended zones (end = -1) are still drawn
auto it = std : : lower_bound ( vec . begin ( ) , vec . end ( ) , m_zvStart - m_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 ;
2017-11-21 01:28:46 +00:00
const auto zitend = std : : lower_bound ( it , vec . end ( ) , m_zvEnd + m_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 ( ) ;
const auto dsz = m_delay * pxns ;
const auto rsz = m_resolution * pxns ;
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 ;
auto & srcloc = GetSourceLocation ( ev . srcloc ) ;
2017-11-11 21:56:05 +00:00
const auto color = GetZoneColor ( ev ) ;
2017-10-12 17:14:03 +00:00
const auto end = 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 ;
const auto nend = GetZoneEnd ( * * it ) ;
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
{
2017-11-14 22:31:24 +00:00
zoneName = GetString ( srcloc . name ) ;
2017-10-12 17:14:03 +00:00
}
2017-09-23 22:07:06 +00:00
else
{
2017-11-11 01:02:47 +00:00
zoneName = 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
2017-10-12 17:14:03 +00:00
if ( ev . end ! = - 1 & & m_lastCpu ! = ev . cpu_end )
{
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
{
// cast to uint64_t, so that unended zones (end = -1) are still drawn
auto it = std : : lower_bound ( vec . begin ( ) , vec . end ( ) , m_zvStart - m_delay , [ ] ( const auto & l , const auto & r ) { return ( uint64_t ) l - > gpuEnd < ( uint64_t ) r ; } ) ;
if ( it = = vec . end ( ) ) return depth ;
2017-11-21 01:28:46 +00:00
const auto zitend = std : : lower_bound ( it , vec . end ( ) , m_zvEnd + m_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 ( ) ;
const auto dsz = m_delay * pxns ;
const auto rsz = m_resolution * pxns ;
depth + + ;
int maxdepth = depth ;
while ( it < zitend )
{
auto & ev = * * it ;
auto & srcloc = GetSourceLocation ( ev . srcloc ) ;
const auto color = GetZoneColor ( ev ) ;
const auto end = 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 ;
const auto nend = GetZoneEnd ( * * it ) ;
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 ;
}
2017-11-14 22:06:45 +00:00
const char * zoneName = 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
} ;
2017-12-09 18:28:12 +00:00
static Vector < LockEvent * > : : iterator GetNextLockEvent ( const Vector < LockEvent * > : : iterator & it , const Vector < LockEvent * > : : 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 ;
}
static Vector < LockEvent * > : : iterator GetNextLockEventShared ( const Vector < LockEvent * > : : iterator & it , const Vector < LockEvent * > : : iterator & end , LockState & nextState , uint64_t threadBit )
{
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 )
{
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 ( ) ;
const auto dsz = m_delay * pxns ;
const auto rsz = m_resolution * pxns ;
2017-10-04 19:27:06 +00:00
int cnt = 0 ;
for ( auto & v : m_lockMap )
{
auto & lockmap = v . second ;
2017-12-10 20:37:39 +00:00
if ( ! lockmap . visible | | ! lockmap . valid ) 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 ;
2017-10-04 19:27:06 +00:00
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
2017-10-05 21:18:24 +00:00
auto vbegin = std : : lower_bound ( tl . begin ( ) , tl . end ( ) , m_zvStart - m_delay , [ ] ( const auto & l , const auto & r ) { return l - > time < r ; } ) ;
2017-11-21 01:28:46 +00:00
const auto vend = std : : lower_bound ( vbegin , tl . end ( ) , m_zvEnd + m_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 ;
auto & srcloc = 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 ( ) ;
2017-11-17 23:51:04 +00:00
ImGui : : Text ( " Lock #% " PRIu32 " : %s " , v . first , GetString ( srcloc . function ) ) ;
ImGui : : Separator ( ) ;
2017-11-11 01:02:47 +00:00
ImGui : : Text ( " %s:%i " , 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
{
2017-10-28 13:33:34 +00:00
auto & marklocdata = GetSourceLocation ( markloc ) ;
ImGui : : Text ( " Lock event location: " ) ;
2017-11-11 01:02:47 +00:00
ImGui : : Text ( " %s " , GetString ( marklocdata . function ) ) ;
ImGui : : Text ( " %s:%i " , 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 )
{
ImGui : : Text ( " Thread \" %s \" has lock. No other threads are waiting. " , GetThreadString ( tid ) ) ;
}
else
{
ImGui : : Text ( " Thread \" %s \" has %i locks. No other threads are waiting. " , GetThreadString ( tid ) , ( * vbegin ) - > lockCount ) ;
}
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 )
{
ImGui : : Text ( " Thread \" %s \" has lock. Blocked threads (%i): " , GetThreadString ( tid ) , TracyCountBits ( ( * vbegin ) - > waitList ) ) ;
}
else
{
ImGui : : Text ( " Thread \" %s \" has %i locks. Blocked threads (%i): " , GetThreadString ( tid ) , ( * vbegin ) - > lockCount , TracyCountBits ( ( * vbegin ) - > waitList ) ) ;
}
auto waitList = ( * vbegin ) - > waitList ;
int t = 0 ;
ImGui : : Indent ( ty ) ;
while ( waitList ! = 0 )
{
if ( waitList & 0x1 )
{
ImGui : : Text ( " \" %s \" " , GetThreadString ( lockmap . threadList [ t ] ) ) ;
}
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 )
{
ImGui : : Text ( " Thread \" %s \" is blocked by other thread: " , GetThreadString ( tid ) ) ;
}
else
{
ImGui : : Text ( " Thread \" %s \" waits to obtain lock after release by thread: " , GetThreadString ( tid ) ) ;
}
ImGui : : Indent ( ty ) ;
ImGui : : Text ( " \" %s \" " , GetThreadString ( lockmap . threadList [ ( * vbegin ) - > lockingThread ] ) ) ;
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 ) ;
ImGui : : Text ( " Thread \" %s \" has lock. No other threads are waiting. " , GetThreadString ( tid ) ) ;
}
else if ( TracyCountBits ( ptr - > sharedList ) = = 1 )
{
ImGui : : Text ( " Thread \" %s \" has a sole shared lock. No other threads are waiting. " , GetThreadString ( tid ) ) ;
}
else
{
ImGui : : Text ( " Thread \" %s \" has shared lock. No other threads are waiting. " , GetThreadString ( tid ) ) ;
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 )
{
ImGui : : Text ( " \" %s \" " , GetThreadString ( lockmap . threadList [ t ] ) ) ;
}
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 ) ;
ImGui : : Text ( " Thread \" %s \" has lock. Blocked threads (%i): " , GetThreadString ( tid ) , TracyCountBits ( ptr - > waitList ) + TracyCountBits ( ptr - > waitShared ) ) ;
}
else if ( TracyCountBits ( ptr - > sharedList ) = = 1 )
{
ImGui : : Text ( " Thread \" %s \" has a sole shared lock. Blocked threads (%i): " , GetThreadString ( tid ) , TracyCountBits ( ptr - > waitList ) + TracyCountBits ( ptr - > waitShared ) ) ;
}
else
2017-10-28 13:33:34 +00:00
{
2017-12-17 18:40:45 +00:00
ImGui : : Text ( " Thread \" %s \" has shared lock. " , GetThreadString ( tid ) ) ;
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 )
{
ImGui : : Text ( " \" %s \" " , GetThreadString ( lockmap . threadList [ t ] ) ) ;
}
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 )
{
ImGui : : Text ( " \" %s \" " , GetThreadString ( lockmap . threadList [ t ] ) ) ;
}
waitList > > = 1 ;
t + + ;
}
auto waitShared = ptr - > waitShared ;
t = 0 ;
while ( waitShared ! = 0 )
{
if ( waitShared & 0x1 )
{
ImGui : : Text ( " \" %s \" " , GetThreadString ( lockmap . threadList [ t ] ) ) ;
}
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 )
{
ImGui : : Text ( " Thread \" %s \" is blocked by other threads (%i): " , GetThreadString ( tid ) , ptr - > lockCount + TracyCountBits ( ptr - > sharedList ) ) ;
}
else
{
ImGui : : Text ( " Thread \" %s \" waits to obtain lock after release by thread: " , GetThreadString ( tid ) ) ;
}
ImGui : : Indent ( ty ) ;
if ( ptr - > lockCount ! = 0 )
{
ImGui : : Text ( " \" %s \" " , GetThreadString ( lockmap . threadList [ ptr - > lockingThread ] ) ) ;
}
auto sharedList = ptr - > sharedList ;
int t = 0 ;
while ( sharedList ! = 0 )
{
if ( sharedList & 0x1 )
{
ImGui : : Text ( " \" %s \" " , GetThreadString ( lockmap . threadList [ t ] ) ) ;
}
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 ] ;
2017-11-11 01:02:47 +00:00
sprintf ( buf , " % " PRIu32 " : %s " , v . first , 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 ) ;
for ( auto & t : v . second . threadList )
{
ImGui : : Text ( " %s " , GetThreadString ( t ) ) ;
}
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
for ( auto & v : m_plots )
{
2017-10-22 11:17:34 +00:00
if ( ! v - > visible ) continue ;
2017-10-13 13:36:16 +00:00
assert ( ! v - > data . empty ( ) ) ;
2017-10-13 12:54:32 +00:00
2017-10-22 11:17:34 +00:00
if ( v - > 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 ) ;
}
const auto txt = GetString ( v - > name ) ;
2017-10-22 11:17:34 +00:00
draw - > AddText ( wpos + ImVec2 ( ty , offset ) , v - > 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 ) )
{
2017-10-22 11:17:34 +00:00
v - > showFull = ! v - > 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
2017-10-22 11:17:34 +00:00
if ( v - > showFull )
2017-10-13 12:54:32 +00:00
{
2017-10-13 13:41:20 +00:00
auto & vec = v - > data ;
2017-12-05 20:24:09 +00:00
auto it = std : : lower_bound ( vec . begin ( ) , vec . end ( ) , m_zvStart - m_delay , [ ] ( const auto & l , const auto & r ) { return l . time < r ; } ) ;
auto end = std : : lower_bound ( it , vec . end ( ) , m_zvEnd + m_resolution , [ ] ( 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 ;
for ( size_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 ;
2017-09-29 20:32:03 +00:00
ImGui : : Begin ( " Zone info " , & show , ImGuiWindowFlags_ShowBorders ) ;
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 ( ) ;
2017-11-14 22:31:24 +00:00
auto & srcloc = GetSourceLocation ( ev . srcloc ) ;
if ( srcloc . name . active )
2017-09-29 19:49:14 +00:00
{
2017-11-14 22:31:24 +00:00
ImGui : : Text ( " Zone name: %s " , GetString ( srcloc . name ) ) ;
2017-09-29 19:49:14 +00:00
}
2017-11-11 01:02:47 +00:00
ImGui : : Text ( " Function: %s " , GetString ( srcloc . function ) ) ;
ImGui : : Text ( " Location: %s:%i " , GetString ( srcloc . file ) , srcloc . line ) ;
2017-11-14 22:31:24 +00:00
if ( ev . text . active )
2017-09-29 19:49:14 +00:00
{
2017-11-14 22:31:24 +00:00
ImGui : : Text ( " User text: %s " , 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 ( ) ;
const auto end = GetZoneEnd ( ev ) ;
2017-09-29 20:13:22 +00:00
const auto ztime = end - ev . start ;
2017-09-29 20:06:31 +00:00
ImGui : : Text ( " Time from start of program: %s " , TimeToString ( ev . start - m_frames [ 0 ] ) ) ;
2017-09-29 20:13:22 +00:00
ImGui : : Text ( " Execution time: %s " , TimeToString ( ztime ) ) ;
ImGui : : Text ( " Without profiling: %s " , TimeToString ( ztime - m_delay * dmul ) ) ;
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
{
2017-09-29 20:32:03 +00:00
const auto cend = GetZoneEnd ( * ev . child [ i ] ) ;
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 ( ) )
{
2017-09-29 20:59:11 +00:00
const auto ty = ImGui : : GetTextLineHeight ( ) ;
2017-09-29 20:32:03 +00:00
ImGui : : Columns ( 2 ) ;
ImGui : : Separator ( ) ;
2017-11-25 12:50:41 +00:00
ImGui : : Text ( " Child zones: %s " , RealToString ( ev . child . size ( ) , true ) ) ;
2017-09-29 20:32:03 +00:00
ImGui : : NextColumn ( ) ;
2017-09-29 20:50:25 +00:00
ImGui : : Text ( " Exclusive time: %s (%.2f%%) " , TimeToString ( ztime - ctime ) , double ( ztime - ctime ) / ztime * 100 ) ;
2017-09-29 20:32:03 +00:00
ImGui : : NextColumn ( ) ;
ImGui : : Separator ( ) ;
2017-10-28 19:50:06 +00:00
for ( size_t i = 0 ; i < ev . child . size ( ) ; i + + )
2017-09-29 20:32:03 +00:00
{
auto & cev = * ev . child [ cti [ i ] ] ;
2017-11-14 22:31:24 +00:00
auto & csl = GetSourceLocation ( cev . srcloc ) ;
if ( csl . name . active )
2017-09-29 20:32:03 +00:00
{
2017-11-14 22:31:24 +00:00
ImGui : : Text ( " %s " , GetString ( csl . name ) ) ;
2017-09-29 20:32:03 +00:00
}
else
{
2017-11-14 22:31:24 +00:00
ImGui : : Text ( " %s " , GetString ( csl . function ) ) ;
2017-09-29 20:32:03 +00:00
}
2017-09-29 20:38:38 +00:00
if ( ImGui : : IsItemHovered ( ) )
{
m_zoneHighlight = & cev ;
if ( ImGui : : IsMouseClicked ( 0 ) )
{
m_zoneInfoWindow = & cev ;
}
if ( ImGui : : IsMouseClicked ( 2 ) )
{
ZoomToZone ( cev ) ;
}
2017-09-29 20:57:22 +00:00
ZoneTooltip ( cev ) ;
2017-09-29 20:38:38 +00:00
}
2017-09-29 20:32:03 +00:00
ImGui : : NextColumn ( ) ;
2017-09-29 20:50:25 +00:00
const auto part = double ( ctt [ cti [ i ] ] ) / ztime ;
char buf [ 128 ] ;
sprintf ( buf , " %s (%.2f%%) " , TimeToString ( ctt [ cti [ i ] ] ) , part * 100 ) ;
2017-09-29 20:59:11 +00:00
ImGui : : ProgressBar ( part , ImVec2 ( - 1 , ty ) , buf ) ;
2017-09-29 20:32:03 +00:00
ImGui : : NextColumn ( ) ;
}
ImGui : : EndColumns ( ) ;
}
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 ;
ImGui : : Begin ( " Zone info " , & show , ImGuiWindowFlags_ShowBorders ) ;
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 ( ) ;
auto & srcloc = GetSourceLocation ( ev . srcloc ) ;
2017-11-14 22:06:45 +00:00
ImGui : : Text ( " Zone name: %s " , GetString ( srcloc . name ) ) ;
2017-11-12 00:25:44 +00:00
ImGui : : Text ( " Function: %s " , GetString ( srcloc . function ) ) ;
ImGui : : Text ( " Location: %s:%i " , GetString ( srcloc . file ) , srcloc . line ) ;
ImGui : : Separator ( ) ;
const auto end = GetZoneEnd ( ev ) ;
const auto ztime = end - ev . gpuStart ;
ImGui : : Text ( " Time from start of program: %s " , TimeToString ( ev . gpuStart - m_frames [ 0 ] ) ) ;
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 ) ) ;
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 + + )
{
const auto cend = GetZoneEnd ( * ev . child [ i ] ) ;
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 ( ) )
{
const auto ty = ImGui : : GetTextLineHeight ( ) ;
ImGui : : Columns ( 2 ) ;
ImGui : : Separator ( ) ;
2017-11-25 12:50:41 +00:00
ImGui : : Text ( " Child zones: %s " , RealToString ( ev . child . size ( ) , true ) ) ;
2017-11-12 00:25:44 +00:00
ImGui : : NextColumn ( ) ;
ImGui : : Text ( " Exclusive time: %s (%.2f%%) " , TimeToString ( ztime - ctime ) , double ( ztime - ctime ) / ztime * 100 ) ;
ImGui : : NextColumn ( ) ;
ImGui : : Separator ( ) ;
for ( size_t i = 0 ; i < ev . child . size ( ) ; i + + )
{
auto & cev = * ev . child [ cti [ i ] ] ;
2017-11-14 22:06:45 +00:00
auto & csl = GetSourceLocation ( cev . srcloc ) ;
ImGui : : Text ( " %s " , GetString ( csl . name ) ) ;
2017-11-12 00:25:44 +00:00
if ( ImGui : : IsItemHovered ( ) )
{
2017-11-12 00:28:07 +00:00
m_gpuHighlight = & cev ;
2017-11-12 00:25:44 +00:00
if ( ImGui : : IsMouseClicked ( 0 ) )
{
m_gpuInfoWindow = & cev ;
}
if ( ImGui : : IsMouseClicked ( 2 ) )
{
ZoomToZone ( cev ) ;
}
ZoneTooltip ( cev ) ;
}
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 ( ) ;
}
ImGui : : EndColumns ( ) ;
}
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 ( ) ;
2017-10-13 11:32:23 +00:00
ImGui : : Begin ( " Options " , & m_showOptions , ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_ShowBorders ) ;
2017-11-11 21:56:05 +00:00
ImGui : : Checkbox ( " Draw GPU zones " , & m_drawGpuZones ) ;
2017-11-30 14:34:52 +00:00
ImGui : : Indent ( tw ) ;
for ( size_t i = 0 ; i < m_gpuData . size ( ) ; i + + )
{
char buf [ 1024 ] ;
sprintf ( buf , " GPU context %zu " , i ) ;
ImGui : : Checkbox ( buf , & m_gpuData [ i ] - > visible ) ;
}
ImGui : : Unindent ( tw ) ;
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 ;
2017-10-22 11:17:34 +00:00
ImGui : : Separator ( ) ;
2017-10-13 11:32:23 +00:00
ImGui : : Checkbox ( " Draw locks " , & m_drawLocks ) ;
2017-10-22 11:32:27 +00:00
ImGui : : SameLine ( ) ;
ImGui : : Checkbox ( " Only contended " , & m_onlyContendedLocks ) ;
2017-10-22 11:25:58 +00:00
ImGui : : Indent ( tw ) ;
for ( auto & l : m_lockMap )
{
2017-12-10 20:37:39 +00:00
if ( l . second . valid )
{
char buf [ 1024 ] ;
sprintf ( buf , " % " PRIu32 " : %s " , l . first , GetString ( GetSourceLocation ( l . second . srcloc ) . function ) ) ;
ImGui : : Checkbox ( buf , & l . second . visible ) ;
}
2017-10-22 11:25:58 +00:00
}
ImGui : : Unindent ( tw ) ;
2017-10-22 11:17:34 +00:00
ImGui : : Separator ( ) ;
2017-10-13 12:54:32 +00:00
ImGui : : Checkbox ( " Draw plots " , & m_drawPlots ) ;
2017-10-22 11:17:34 +00:00
ImGui : : Indent ( tw ) ;
for ( auto & p : m_plots )
{
ImGui : : Checkbox ( GetString ( p - > name ) , & p - > visible ) ;
}
ImGui : : Unindent ( tw ) ;
2017-10-22 11:13:26 +00:00
ImGui : : Separator ( ) ;
ImGui : : Text ( " Visible threads: " ) ;
ImGui : : Indent ( tw ) ;
for ( auto & t : m_threads )
{
ImGui : : Checkbox ( GetThreadString ( t - > id ) , & t - > visible ) ;
}
ImGui : : Unindent ( tw ) ;
2017-10-13 11:32:23 +00:00
ImGui : : End ( ) ;
}
2017-10-14 12:36:30 +00:00
void View : : DrawMessages ( )
{
ImGui : : Begin ( " Messages " , & m_showMessages , ImGuiWindowFlags_ShowBorders ) ;
for ( auto & v : m_messages )
{
2017-10-16 23:20:10 +00:00
char tmp [ 64 * 1024 ] ;
2017-11-11 00:39:34 +00:00
sprintf ( tmp , " %10s | %s " , TimeToString ( v - > time - m_frames [ 0 ] ) , 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 ( ) ;
}
2017-10-22 13:37:24 +00:00
uint32_t View : : GetZoneColor ( const ZoneEvent & ev )
2017-10-01 17:31:22 +00:00
{
2017-11-11 21:56:05 +00:00
auto & srcloc = GetSourceLocation ( ev . srcloc ) ;
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
{
2017-11-11 21:56:05 +00:00
auto & srcloc = 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
{
2017-10-08 09:38:03 +00:00
const auto end = GetZoneEnd ( ev ) ;
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 )
{
const auto end = GetZoneEnd ( ev ) ;
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
auto & srcloc = GetSourceLocation ( ev . srcloc ) ;
2017-11-11 01:02:47 +00:00
const auto filename = 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
{
2017-11-14 22:31:24 +00:00
zoneName = GetString ( srcloc . name ) ;
2017-11-11 01:02:47 +00:00
func = GetString ( srcloc . function ) ;
2017-09-29 20:55:24 +00:00
}
else
{
2017-11-11 01:02:47 +00:00
func = zoneName = GetString ( srcloc . function ) ;
2017-09-29 20:55:24 +00:00
}
const auto end = GetZoneEnd ( ev ) ;
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 ) ;
ImGui : : Text ( " Execution time: %s " , TimeToString ( end - ev . start ) ) ;
ImGui : : Text ( " Without profiling: %s " , TimeToString ( end - ev . start - m_delay * dmul ) ) ;
2017-10-01 17:21:25 +00:00
if ( ev . cpu_start ! = - 1 )
{
if ( ev . end = = - 1 | | ev . cpu_start = = ev . cpu_end )
{
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 ( ) ;
2017-11-14 22:31:24 +00:00
ImGui : : TextColored ( ImVec4 ( 0xCC / 255.f , 0xCC / 255.f , 0x22 / 255.f , 1.f ) , " %s " , 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 )
{
auto & srcloc = GetSourceLocation ( ev . srcloc ) ;
2017-11-18 12:47:05 +00:00
const auto name = GetString ( srcloc . name ) ;
2017-11-11 21:56:05 +00:00
const auto filename = GetString ( srcloc . file ) ;
const auto line = srcloc . line ;
const auto func = GetString ( srcloc . function ) ;
const auto end = GetZoneEnd ( ev ) ;
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 ) ;
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
{
for ( auto & thread : m_threads )
{
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 ;
2017-10-22 15:09:33 +00:00
if ( zone . end ! = - 1 & & ( * 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
{
for ( auto & ctx : m_gpuData )
{
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 ;
if ( zone . gpuEnd ! = - 1 & & ( * it ) - > gpuStart > zone . gpuEnd ) break ;
if ( * it = = & zone ) return parent ;
if ( ( * it ) - > child . empty ( ) ) break ;
parent = * it ;
timeline = & parent - > child ;
}
}
return nullptr ;
}
2017-09-30 14:20:08 +00:00
void View : : Write ( FileWrite & f )
{
2017-09-30 14:58:02 +00:00
f . Write ( & m_delay , sizeof ( m_delay ) ) ;
f . Write ( & m_resolution , sizeof ( m_resolution ) ) ;
f . Write ( & m_timerMul , sizeof ( m_timerMul ) ) ;
2017-12-09 19:05:34 +00:00
f . Write ( & m_lastTime , sizeof ( m_lastTime ) ) ;
2017-09-30 14:58:02 +00:00
2017-10-03 21:29:48 +00:00
uint64_t sz = m_captureName . size ( ) ;
f . Write ( & sz , sizeof ( sz ) ) ;
f . Write ( m_captureName . c_str ( ) , sz ) ;
sz = m_frames . size ( ) ;
2017-09-30 14:20:08 +00:00
f . Write ( & sz , sizeof ( sz ) ) ;
f . Write ( m_frames . data ( ) , sizeof ( uint64_t ) * sz ) ;
2017-11-10 16:45:19 +00:00
sz = m_stringData . size ( ) ;
2017-09-30 14:20:08 +00:00
f . Write ( & sz , sizeof ( sz ) ) ;
2017-11-10 16:45:19 +00:00
for ( auto & v : m_stringData )
2017-09-30 14:20:08 +00:00
{
uint64_t ptr = ( uint64_t ) v ;
f . Write ( & ptr , sizeof ( ptr ) ) ;
sz = strlen ( v ) ;
f . Write ( & sz , sizeof ( sz ) ) ;
f . Write ( v , sz ) ;
}
2017-11-10 18:30:04 +00:00
sz = m_strings . size ( ) ;
f . Write ( & sz , sizeof ( sz ) ) ;
for ( auto & v : m_strings )
{
f . Write ( & v . first , sizeof ( v . first ) ) ;
uint64_t ptr = ( uint64_t ) v . second ;
f . Write ( & ptr , sizeof ( ptr ) ) ;
}
2017-11-10 18:24:12 +00:00
sz = m_threadNames . size ( ) ;
f . Write ( & sz , sizeof ( sz ) ) ;
for ( auto & v : m_threadNames )
{
f . Write ( & v . first , sizeof ( v . first ) ) ;
uint64_t ptr = ( uint64_t ) v . second ;
f . Write ( & ptr , sizeof ( ptr ) ) ;
}
2017-09-30 14:20:08 +00:00
sz = m_sourceLocation . size ( ) ;
f . Write ( & sz , sizeof ( sz ) ) ;
for ( auto & v : m_sourceLocation )
{
f . Write ( & v . first , sizeof ( v . first ) ) ;
f . Write ( & v . second , sizeof ( v . second ) ) ;
}
2017-10-28 20:14:01 +00:00
sz = m_sourceLocationExpand . size ( ) ;
f . Write ( & sz , sizeof ( sz ) ) ;
for ( auto & v : m_sourceLocationExpand )
{
f . Write ( & v , sizeof ( v ) ) ;
}
2017-11-05 20:36:22 +00:00
sz = m_sourceLocationPayload . size ( ) ;
f . Write ( & sz , sizeof ( sz ) ) ;
for ( auto & v : m_sourceLocationPayload )
{
2017-11-11 01:02:47 +00:00
f . Write ( v , sizeof ( * v ) ) ;
2017-11-05 20:36:22 +00:00
}
2017-10-04 18:10:38 +00:00
sz = m_lockMap . size ( ) ;
f . Write ( & sz , sizeof ( sz ) ) ;
for ( auto & v : m_lockMap )
{
f . Write ( & v . first , sizeof ( v . first ) ) ;
2017-10-04 19:36:47 +00:00
f . Write ( & v . second . srcloc , sizeof ( v . second . srcloc ) ) ;
2017-12-10 20:37:39 +00:00
f . Write ( & v . second . type , sizeof ( v . second . type ) ) ;
f . Write ( & v . second . valid , sizeof ( v . second . valid ) ) ;
2017-10-08 21:03:38 +00:00
sz = v . second . threadList . size ( ) ;
2017-10-04 18:10:38 +00:00
f . Write ( & sz , sizeof ( sz ) ) ;
2017-10-08 21:03:38 +00:00
for ( auto & t : v . second . threadList )
2017-10-04 18:10:38 +00:00
{
f . Write ( & t , sizeof ( t ) ) ;
}
sz = v . second . timeline . size ( ) ;
f . Write ( & sz , sizeof ( sz ) ) ;
2017-12-17 17:44:31 +00:00
if ( v . second . type = = LockType : : Lockable )
{
for ( auto & lev : v . second . timeline )
{
f . Write ( lev , sizeof ( LockEvent ) ) ;
}
}
else
2017-10-04 18:10:38 +00:00
{
2017-12-17 17:44:31 +00:00
for ( auto & lev : v . second . timeline )
{
f . Write ( lev , sizeof ( LockEventShared ) ) ;
}
2017-10-04 18:10:38 +00:00
}
}
2017-10-14 13:26:02 +00:00
sz = m_messages . size ( ) ;
f . Write ( & sz , sizeof ( sz ) ) ;
for ( auto & v : m_messages )
{
const auto ptr = ( uint64_t ) v ;
f . Write ( & ptr , sizeof ( ptr ) ) ;
2017-11-11 00:39:34 +00:00
f . Write ( v , sizeof ( * v ) ) ;
2017-10-14 13:26:02 +00:00
}
2017-09-30 14:20:08 +00:00
sz = m_threads . size ( ) ;
f . Write ( & sz , sizeof ( sz ) ) ;
for ( auto & thread : m_threads )
{
f . Write ( & thread - > id , sizeof ( thread - > id ) ) ;
2017-11-18 00:14:16 +00:00
f . Write ( & thread - > count , sizeof ( thread - > count ) ) ;
2017-09-30 14:20:08 +00:00
WriteTimeline ( f , thread - > timeline ) ;
2017-10-14 13:26:02 +00:00
sz = thread - > messages . size ( ) ;
f . Write ( & sz , sizeof ( sz ) ) ;
for ( auto & v : thread - > messages )
{
auto ptr = uint64_t ( v ) ;
f . Write ( & ptr , sizeof ( ptr ) ) ;
}
2017-09-30 14:20:08 +00:00
}
2017-10-13 14:04:20 +00:00
2017-11-12 00:12:28 +00:00
sz = m_gpuData . size ( ) ;
f . Write ( & sz , sizeof ( sz ) ) ;
for ( auto & ctx : m_gpuData )
{
2017-11-13 23:48:26 +00:00
f . Write ( & ctx - > thread , sizeof ( ctx - > thread ) ) ;
2017-11-17 23:32:15 +00:00
f . Write ( & ctx - > accuracyBits , sizeof ( ctx - > accuracyBits ) ) ;
2017-11-18 00:07:28 +00:00
f . Write ( & ctx - > count , sizeof ( ctx - > count ) ) ;
2017-11-12 00:12:28 +00:00
WriteTimeline ( f , ctx - > timeline ) ;
}
2017-10-13 14:04:20 +00:00
sz = m_plots . size ( ) ;
f . Write ( & sz , sizeof ( sz ) ) ;
for ( auto & plot : m_plots )
{
f . Write ( & plot - > name , sizeof ( plot - > name ) ) ;
f . Write ( & plot - > min , sizeof ( plot - > min ) ) ;
f . Write ( & plot - > max , sizeof ( plot - > max ) ) ;
sz = plot - > data . size ( ) ;
f . Write ( & sz , sizeof ( sz ) ) ;
2017-12-05 20:24:09 +00:00
f . Write ( plot - > data . data ( ) , sizeof ( PlotItem ) * sz ) ;
2017-10-13 14:04:20 +00:00
}
2017-09-30 14:20:08 +00:00
}
2017-10-22 13:37:24 +00:00
void View : : WriteTimeline ( FileWrite & f , const Vector < ZoneEvent * > & vec )
2017-09-30 14:20:08 +00:00
{
uint64_t sz = vec . size ( ) ;
f . Write ( & sz , sizeof ( sz ) ) ;
for ( auto & v : vec )
{
f . Write ( & v - > start , sizeof ( v - > start ) ) ;
f . Write ( & v - > end , sizeof ( v - > end ) ) ;
f . Write ( & v - > srcloc , sizeof ( v - > srcloc ) ) ;
2017-10-01 17:16:44 +00:00
f . Write ( & v - > cpu_start , sizeof ( v - > cpu_start ) ) ;
f . Write ( & v - > cpu_end , sizeof ( v - > cpu_end ) ) ;
2017-10-22 14:40:15 +00:00
f . Write ( & v - > text , sizeof ( v - > text ) ) ;
2017-09-30 14:20:08 +00:00
WriteTimeline ( f , v - > child ) ;
}
}
2017-11-12 00:12:28 +00:00
void View : : WriteTimeline ( FileWrite & f , const Vector < GpuEvent * > & vec )
{
uint64_t sz = vec . size ( ) ;
f . Write ( & sz , sizeof ( sz ) ) ;
for ( auto & v : vec )
{
f . Write ( & v - > cpuStart , sizeof ( v - > cpuStart ) ) ;
f . Write ( & v - > cpuEnd , sizeof ( v - > cpuEnd ) ) ;
f . Write ( & v - > gpuStart , sizeof ( v - > gpuStart ) ) ;
f . Write ( & v - > gpuEnd , sizeof ( v - > gpuEnd ) ) ;
f . Write ( & v - > srcloc , sizeof ( v - > srcloc ) ) ;
WriteTimeline ( f , v - > child ) ;
}
}
2017-11-10 17:22:41 +00:00
void View : : ReadTimeline ( FileRead & f , Vector < ZoneEvent * > & vec )
2017-09-30 14:58:02 +00:00
{
uint64_t sz ;
f . Read ( & sz , sizeof ( sz ) ) ;
2017-09-30 23:54:40 +00:00
vec . reserve ( sz ) ;
2017-09-30 14:58:02 +00:00
for ( uint64_t i = 0 ; i < sz ; i + + )
{
2017-11-16 01:19:52 +00:00
auto zone = m_slab . AllocInit < ZoneEvent > ( ) ;
2017-11-15 21:13:23 +00:00
2017-09-30 14:59:03 +00:00
m_zonesCnt + + ;
2017-09-30 14:58:02 +00:00
vec . push_back ( zone ) ;
f . Read ( & zone - > start , sizeof ( zone - > start ) ) ;
f . Read ( & zone - > end , sizeof ( zone - > end ) ) ;
f . Read ( & zone - > srcloc , sizeof ( zone - > srcloc ) ) ;
2017-10-01 17:16:44 +00:00
f . Read ( & zone - > cpu_start , sizeof ( zone - > cpu_start ) ) ;
f . Read ( & zone - > cpu_end , sizeof ( zone - > cpu_end ) ) ;
2017-10-22 14:40:15 +00:00
f . Read ( & zone - > text , sizeof ( zone - > text ) ) ;
2017-11-10 17:22:41 +00:00
ReadTimeline ( f , zone - > child ) ;
2017-09-30 14:58:02 +00:00
}
}
2017-11-12 00:12:28 +00:00
void View : : ReadTimeline ( FileRead & f , Vector < GpuEvent * > & vec )
{
uint64_t sz ;
f . Read ( & sz , sizeof ( sz ) ) ;
vec . reserve ( sz ) ;
for ( uint64_t i = 0 ; i < sz ; i + + )
{
2017-11-16 01:19:52 +00:00
auto zone = m_slab . AllocInit < GpuEvent > ( ) ;
2017-11-15 21:21:02 +00:00
2017-11-12 00:12:28 +00:00
vec . push_back ( zone ) ;
f . Read ( & zone - > cpuStart , sizeof ( zone - > cpuStart ) ) ;
f . Read ( & zone - > cpuEnd , sizeof ( zone - > cpuEnd ) ) ;
f . Read ( & zone - > gpuStart , sizeof ( zone - > gpuStart ) ) ;
f . Read ( & zone - > gpuEnd , sizeof ( zone - > gpuEnd ) ) ;
f . Read ( & zone - > srcloc , sizeof ( zone - > srcloc ) ) ;
ReadTimeline ( f , zone - > child ) ;
}
}
2017-09-12 23:33:50 +00:00
}