Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/wolfpld/tracy.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBartosz Taudul <wolf@nereid.pl>2022-07-30 22:29:44 +0300
committerBartosz Taudul <wolf@nereid.pl>2022-07-30 22:29:44 +0300
commite0f813d9e901afa5bdb30fc2de0b5e7d01b87ed5 (patch)
tree8cef9a5e2a3a9190c301059cb3c5e91fb2a0130f
parent91b002267ea5511cab5d6537b3ab7e5be5392cb9 (diff)
Add support for Vsync capture on Linux.
-rw-r--r--public/client/TracySysTrace.cpp91
1 files changed, 84 insertions, 7 deletions
diff --git a/public/client/TracySysTrace.cpp b/public/client/TracySysTrace.cpp
index 2198536d..9fc07117 100644
--- a/public/client/TracySysTrace.cpp
+++ b/public/client/TracySysTrace.cpp
@@ -661,6 +661,7 @@ enum TraceEventId
EventCacheMiss,
EventBranchRetired,
EventBranchMiss,
+ EventVsync,
EventContextSwitch,
EventWakeup,
};
@@ -751,13 +752,17 @@ bool SysTraceStart( int64_t& samplingPeriod )
TracyDebug( "perf_event_paranoid: %i\n", paranoidLevel );
#endif
- int switchId = -1, wakeupId = -1;
+ int switchId = -1, wakeupId = -1, vsyncId = -1;
const auto switchIdStr = ReadFile( "/sys/kernel/debug/tracing/events/sched/sched_switch/id" );
if( switchIdStr ) switchId = atoi( switchIdStr );
const auto wakeupIdStr = ReadFile( "/sys/kernel/debug/tracing/events/sched/sched_wakeup/id" );
if( wakeupIdStr ) wakeupId = atoi( wakeupIdStr );
+ const auto vsyncIdStr = ReadFile( "/sys/kernel/debug/tracing/events/drm/drm_vblank_event/id" );
+ if( vsyncIdStr ) vsyncId = atoi( vsyncIdStr );
- TracyDebug( "sched_switch id: %i\nsched_wakeup id: %i\n", switchId, wakeupId );
+ TracyDebug( "sched_switch id: %i\n", switchId );
+ TracyDebug( "sched_wakeup id: %i\n", wakeupId );
+ TracyDebug( "drm_vblank_event id: %i\n", vsyncId );
#ifdef TRACY_NO_SAMPLE_RETIREMENT
const bool noRetirement = true;
@@ -787,6 +792,13 @@ bool SysTraceStart( int64_t& samplingPeriod )
const bool noCtxSwitch = noCtxSwitchEnv && noCtxSwitchEnv[0] == '1';
#endif
+#ifdef TRACY_NO_VSYNC_CAPTURE
+ const bool noVsync = true;
+#else
+ const char* noVsyncEnv = GetEnvVar( "TRACY_NO_VSYNC_CAPTURE" );
+ const bool noVsync = noVsyncEnv && noVsyncEnv[0] == '1';
+#endif
+
samplingPeriod = GetSamplingPeriod();
uint32_t currentPid = (uint32_t)getpid();
@@ -797,7 +809,8 @@ bool SysTraceStart( int64_t& samplingPeriod )
2 + // CPU cycles + instructions retired
2 + // cache reference + miss
2 + // branch retired + miss
- 2 // context switches + wakeups
+ 2 + // context switches + wakeups
+ 1 // vsync
);
s_ring = (RingBuffer*)tracy_malloc( sizeof( RingBuffer ) * maxNumBuffers );
s_numBuffers = 0;
@@ -973,6 +986,37 @@ bool SysTraceStart( int64_t& samplingPeriod )
s_ctxBufferIdx = s_numBuffers;
+ // vsync
+ if( !noVsync && vsyncId != -1 )
+ {
+ pe = {};
+ pe.type = PERF_TYPE_TRACEPOINT;
+ pe.size = sizeof( perf_event_attr );
+ pe.sample_period = 1;
+ pe.sample_type = PERF_SAMPLE_TIME | PERF_SAMPLE_RAW;
+ pe.disabled = 1;
+ pe.config = vsyncId;
+#if !defined TRACY_HW_TIMER || !( defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64 )
+ pe.use_clockid = 1;
+ pe.clockid = CLOCK_MONOTONIC_RAW;
+#endif
+
+ TracyDebug( "Setup vsync capture\n" );
+ for( int i=0; i<s_numCpus; i++ )
+ {
+ const int fd = perf_event_open( &pe, -1, i, -1, PERF_FLAG_FD_CLOEXEC );
+ if( fd != -1 )
+ {
+ new( s_ring+s_numBuffers ) RingBuffer( 64*1024, fd, EventVsync, i );
+ if( s_ring[s_numBuffers].IsValid() )
+ {
+ s_numBuffers++;
+ TracyDebug( " Core %i ok\n", i );
+ }
+ }
+ }
+ }
+
// context switches
if( !noCtxSwitch && switchId != -1 )
{
@@ -1307,7 +1351,8 @@ void SysTraceWorker( void* ptr )
t0 = ring.ConvertTimeToTsc( t0 );
#endif
- if( ring.GetId() == EventContextSwitch )
+ const auto rid = ring.GetId();
+ if( rid == EventContextSwitch )
{
// Layout:
// u64 time
@@ -1375,10 +1420,8 @@ void SysTraceWorker( void* ptr )
TracyLfqCommit;
}
}
- else
+ else if( rid == EventWakeup )
{
- assert( ring.GetId() == EventWakeup );
-
// Layout:
// u64 time
// u32 size
@@ -1400,6 +1443,40 @@ void SysTraceWorker( void* ptr )
MemWrite( &item->threadWakeup.thread, pid );
TracyLfqCommit;
}
+ else
+ {
+ assert( rid == EventVsync );
+ // Layout:
+ // u64 time
+ // u32 size
+ // u8 data[size]
+ // Data (not ABI stable):
+ // u8 hdr[8]
+ // i32 crtc
+ // u32 seq
+ // i64 ktime
+ // u8 high precision
+
+ offset += sizeof( perf_event_header ) + sizeof( uint64_t ) + sizeof( uint32_t ) + 8;
+
+ int32_t crtc;
+ ring.Read( &crtc, offset, sizeof( int32_t ) );
+
+ // Note: The timestamp value t0 might be off by a number of microseconds from the
+ // true hardware vblank event. The ktime value should be used instead, but it is
+ // measured in CLOCK_MONOTONIC time. Tracy only supports the timestamp counter
+ // register (TSC) or CLOCK_MONOTONIC_RAW clock.
+#if 0
+ offset += sizeof( uint32_t ) * 2;
+ int64_t ktime;
+ ring.Read( &ktime, offset, sizeof( int64_t ) );
+#endif
+
+ TracyLfqPrepare( QueueType::FrameVsync );
+ MemWrite( &item->frameVsync.id, crtc );
+ MemWrite( &item->frameVsync.time, t0 );
+ TracyLfqCommit;
+ }
rbPos += hdr.size;
if( rbPos == end[sel] )