diff --git a/public/client/TracySysTrace.cpp b/public/client/TracySysTrace.cpp index 8dd9d995..cc89d5de 100644 --- a/public/client/TracySysTrace.cpp +++ b/public/client/TracySysTrace.cpp @@ -66,66 +66,6 @@ namespace tracy static DWORD s_pid; -struct CSwitch -{ - uint32_t newThreadId; - uint32_t oldThreadId; - int8_t newThreadPriority; - int8_t oldThreadPriority; - uint8_t previousCState; - int8_t spareByte; - int8_t oldThreadWaitReason; - int8_t oldThreadWaitMode; - int8_t oldThreadState; - int8_t oldThreadWaitIdealProcessor; - uint32_t newThreadWaitTime; - uint32_t reserved; -}; - -struct ReadyThread -{ - uint32_t threadId; - int8_t adjustReason; - int8_t adjustIncrement; - int8_t flag; - int8_t reserverd; -}; - -struct ThreadTrace -{ - uint32_t processId; - uint32_t threadId; - uint32_t stackBase; - uint32_t stackLimit; - uint32_t userStackBase; - uint32_t userStackLimit; - uint32_t startAddr; - uint32_t win32StartAddr; - uint32_t tebBase; - uint32_t subProcessTag; -}; - -struct StackWalkEvent -{ - uint64_t eventTimeStamp; - uint32_t stackProcess; - uint32_t stackThread; - uint64_t stack[192]; -}; - -struct VSyncInfo -{ - void* dxgAdapter; - uint32_t vidPnTargetId; - uint64_t scannedPhysicalAddress; - uint32_t vidPnSourceId; - uint32_t frameNumber; - int64_t frameQpcTime; - void* hFlipDevice; - uint32_t flipType; - uint64_t flipFenceId; -}; - extern "C" typedef NTSTATUS (WINAPI *t_NtQueryInformationThread)( HANDLE, THREADINFOCLASS, PVOID, ULONG, PULONG ); extern "C" typedef BOOL (WINAPI *t_EnumProcessModules)( HANDLE, HMODULE*, DWORD, LPDWORD ); extern "C" typedef BOOL (WINAPI *t_GetModuleInformation)( HANDLE, HMODULE, LPMODULEINFO, DWORD ); @@ -154,9 +94,9 @@ void WINAPI EventRecordCallback( PEVENT_RECORD record ) switch( hdr.ProviderId.Data1 ) { case etw::ThreadGuid.Data1: - if( hdr.EventDescriptor.Opcode == 36 ) + if( hdr.EventDescriptor.Opcode == etw::CSwitch::Opcode ) { - const auto cswitch = (const CSwitch*)record->UserData; + const auto cswitch = (const etw::CSwitch*)record->UserData; TracyLfqPrepare( QueueType::ContextSwitch ); MemWrite( &item->contextSwitch.time, hdr.TimeStamp.QuadPart ); @@ -170,9 +110,9 @@ void WINAPI EventRecordCallback( PEVENT_RECORD record ) MemWrite( &item->contextSwitch.previousCState, cswitch->previousCState ); TracyLfqCommit; } - else if( hdr.EventDescriptor.Opcode == 50 ) + else if( hdr.EventDescriptor.Opcode == etw::ReadyThread::Opcode ) { - const auto rt = (const ReadyThread*)record->UserData; + const auto rt = (const etw::ReadyThread*)record->UserData; TracyLfqPrepare( QueueType::ThreadWakeup ); MemWrite( &item->threadWakeup.time, hdr.TimeStamp.QuadPart ); @@ -182,13 +122,13 @@ void WINAPI EventRecordCallback( PEVENT_RECORD record ) MemWrite( &item->threadWakeup.adjustIncrement, rt->adjustIncrement ); TracyLfqCommit; } - else if( hdr.EventDescriptor.Opcode == 1 || hdr.EventDescriptor.Opcode == 3 ) + else if( hdr.EventDescriptor.Opcode == etw::ThreadStart::Opcode || hdr.EventDescriptor.Opcode == etw::ThreadDCStart::Opcode ) { - const auto tt = (const ThreadTrace*)record->UserData; + const auto ti = (const etw::ThreadInfo*)record->UserData; - uint64_t tid = tt->threadId; + uint64_t tid = ti->threadId; if( tid == 0 ) return; - uint64_t pid = tt->processId; + uint64_t pid = ti->processId; TracyLfqPrepare( QueueType::TidToPid ); MemWrite( &item->tidToPid.tid, tid ); MemWrite( &item->tidToPid.pid, pid ); @@ -196,9 +136,9 @@ void WINAPI EventRecordCallback( PEVENT_RECORD record ) } break; case etw::StackWalkGuid.Data1: - if( hdr.EventDescriptor.Opcode == 32 ) + if( hdr.EventDescriptor.Opcode == etw::StackWalkEvent::Opcode ) { - const auto sw = (const StackWalkEvent*)record->UserData; + const auto sw = (const etw::StackWalkEvent*)record->UserData; if( sw->stackProcess == s_pid ) { const uint64_t sz = ( record->UserDataLength - 16 ) / 8; @@ -217,9 +157,9 @@ void WINAPI EventRecordCallback( PEVENT_RECORD record ) } break; case etw::DxgKrnlGuid.Data1: - assert( hdr.EventDescriptor.Id == 0x0011 ); + assert( hdr.EventDescriptor.Id == etw::VSyncInfo::EventId ); { - const auto vs = (const VSyncInfo*)record->UserData; + const auto vs = (const etw::VSyncInfo*)record->UserData; TracyLfqPrepare( QueueType::FrameVsync ); MemWrite( &item->frameVsync.time, hdr.TimeStamp.QuadPart ); MemWrite( &item->frameVsync.id, vs->vidPnTargetId ); diff --git a/public/client/windows/TracyETW.cpp b/public/client/windows/TracyETW.cpp index 4446ec10..46abb994 100644 --- a/public/client/windows/TracyETW.cpp +++ b/public/client/windows/TracyETW.cpp @@ -1,6 +1,7 @@ +#include +#include #include #include -#include #include #include @@ -43,7 +44,7 @@ static ULONG ETWError( ULONG result ) return result; ZoneScopedC( tracy::Color::Red4 ); char message[128] = {}; - size_t written = snprintf( message, sizeof( message ), "ETW Error %u (0x%x): ", result, result ); + int written = snprintf( message, sizeof( message ), "ETW Error %u (0x%x): ", result, result ); written += FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, @@ -282,5 +283,91 @@ static ULONG EventConsumerLoop( PROCESSTRACE_HANDLE hEventConsumer ) return status; } +struct CSwitch +{ + // V2 fields: + static constexpr UCHAR Opcode = 36; + uint32_t newThreadId; + uint32_t oldThreadId; + int8_t newThreadPriority; + int8_t oldThreadPriority; + uint8_t previousCState; + int8_t spareByte; + int8_t oldThreadWaitReason; + int8_t oldThreadWaitMode; + int8_t oldThreadState; + int8_t oldThreadWaitIdealProcessor; + uint32_t newThreadWaitTime; + uint32_t reserved; +}; +static_assert(sizeof(CSwitch) == 24, "unexpected CSwitch struct size/alignment"); + +struct ReadyThread +{ + // V2 fields: + static constexpr UCHAR Opcode = 50; + uint32_t threadId; + int8_t adjustReason; + int8_t adjustIncrement; + int8_t flag; + int8_t reserverd; +}; +static_assert(sizeof(ReadyThread) == 8, "unexpected ReadyThread struct size/alignment"); + +struct ThreadInfo +{ + // V0 (Thread_V0_TypeGroup1) fields: + uint32_t processId; + uint32_t threadId; + // NOTE: we only care about PID and TID for now, and these two are "invariant" + // across all revisions (versions) of this event. As such, let's omit the other + // fields since they vary based on the event version; their sizes also vary by + // target architecture (32bit or 64bit), and this is not even mentioned in the + // MSDN documentation, and worse, have not been updated in the official schemas + // either (which ETW Explorer uses), but can be introspected via the TDH API. +}; +static_assert(sizeof(ThreadInfo) == 8, "unexpected ThreadInfo struct size/alignment"); + +struct ThreadStart : public ThreadInfo +{ + static constexpr UCHAR Opcode = 1; +}; +static_assert(sizeof(ThreadStart) == 8, "unexpected ThreadStart struct size/alignment"); + +// DC: Data Collection (associated with the "rundown" phase) +struct ThreadDCStart : public ThreadInfo +{ + static constexpr UCHAR Opcode = 3; +}; +static_assert(sizeof(ThreadDCStart) == 8, "unexpected ThreadDCStart struct size/alignment"); + +struct StackWalkEvent +{ + // V2 fields: + static constexpr UCHAR Opcode = 32; + uint64_t eventTimeStamp; + uint32_t stackProcess; + uint32_t stackThread; + uint64_t stack[192]; // arbitrary upperbound limit; schema stops at [32] +}; +static_assert(offsetof(StackWalkEvent, stackProcess) == 8, "unexpected StackWalkEvent struct size/alignment"); +static_assert(offsetof(StackWalkEvent, stackThread) == 12, "unexpected StackWalkEvent struct size/alignment"); +static_assert(offsetof(StackWalkEvent, stack) == 16, "unexpected StackWalkEvent struct size/alignment"); + +struct VSyncInfo +{ + static constexpr USHORT EventId = 17; // 0x11 + void* dxgAdapter; + uint32_t vidPnTargetId; + uint64_t scannedPhysicalAddress; + uint32_t vidPnSourceId; + uint32_t frameNumber; + int64_t frameQpcTime; + void* hFlipDevice; + uint32_t flipType; + uint64_t flipFenceId; +}; +static_assert(sizeof(VSyncInfo) == 64, "unexpected VSyncInfo struct size/alignment"); + } }