-
Notifications
You must be signed in to change notification settings - Fork 37
Add CaptureMask support #34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 34 commits
cf74c37
315486c
d45f9ee
f44da09
0ec85dc
3a7688b
332a605
867b6d7
31f7c93
d9f7aea
fd800aa
4a6ace5
bbec690
8283b2e
78306a4
e5ed1dc
4a58c70
942e009
7142ed6
82609e4
59ac96c
f6094aa
9eee0e4
253ae9f
ae7e72b
8a812a9
a9ab8f3
6b6fdf8
1528331
1e43e26
601d77f
a57664a
5d3dab5
f6a294a
4803123
1bb58df
6eb92bf
5632876
e9819c3
5cd97fb
2de388f
188e049
43363d9
7a8ab0e
5a4c20d
5e13c0f
717a6f5
f69d3d4
c1be146
6f045a3
bbb7bdb
6a7df4e
819f385
0c42535
d8323e2
4bc9e96
b5875b8
5842a68
9b5582d
dc1acde
b267c8a
7afbdd3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,152 @@ | ||
| // Copyright © 2026 CCP ehf. | ||
|
|
||
| #include "include/CcpColorConstants.h" | ||
|
|
||
| std::string_view CcpColorToString( CcpColor color ) | ||
| { | ||
| // For colors sharing the same RGB value (Aqua/Cyan, Fuchsia/Magenta, and the | ||
| // various *Gray/*Grey pairs), all names sharing that value are returned. | ||
| switch( color ) | ||
| { | ||
| case CcpColor::AliceBlue: return "AliceBlue"; | ||
| case CcpColor::AntiqueWhite: return "AntiqueWhite"; | ||
| case CcpColor::Aqua: return "Aqua / Cyan"; | ||
| case CcpColor::Aquamarine: return "Aquamarine"; | ||
| case CcpColor::Azure: return "Azure"; | ||
| case CcpColor::Beige: return "Beige"; | ||
| case CcpColor::Bisque: return "Bisque"; | ||
| case CcpColor::Black: return "Black"; | ||
| case CcpColor::BlanchedAlmond: return "BlanchedAlmond"; | ||
| case CcpColor::Blue: return "Blue"; | ||
| case CcpColor::BlueViolet: return "BlueViolet"; | ||
| case CcpColor::Brown: return "Brown"; | ||
| case CcpColor::BurlyWood: return "BurlyWood"; | ||
| case CcpColor::CadetBlue: return "CadetBlue"; | ||
| case CcpColor::Chartreuse: return "Chartreuse"; | ||
| case CcpColor::Chocolate: return "Chocolate"; | ||
| case CcpColor::Coral: return "Coral"; | ||
| case CcpColor::CornflowerBlue: return "CornflowerBlue"; | ||
| case CcpColor::Cornsilk: return "Cornsilk"; | ||
| case CcpColor::Crimson: return "Crimson"; | ||
| case CcpColor::DarkBlue: return "DarkBlue"; | ||
| case CcpColor::DarkCyan: return "DarkCyan"; | ||
| case CcpColor::DarkGoldenrod: return "DarkGoldenrod"; | ||
| case CcpColor::DarkGray: return "DarkGray / DarkGrey"; | ||
| case CcpColor::DarkGreen: return "DarkGreen"; | ||
| case CcpColor::DarkKhaki: return "DarkKhaki"; | ||
| case CcpColor::DarkMagenta: return "DarkMagenta"; | ||
| case CcpColor::DarkOliveGreen: return "DarkOliveGreen"; | ||
| case CcpColor::DarkOrange: return "DarkOrange"; | ||
| case CcpColor::DarkOrchid: return "DarkOrchid"; | ||
| case CcpColor::DarkRed: return "DarkRed"; | ||
| case CcpColor::DarkSalmon: return "DarkSalmon"; | ||
| case CcpColor::DarkSeaGreen: return "DarkSeaGreen"; | ||
| case CcpColor::DarkSlateBlue: return "DarkSlateBlue"; | ||
| case CcpColor::DarkSlateGray: return "DarkSlateGray / DarkSlateGrey"; | ||
| case CcpColor::DarkTurquoise: return "DarkTurquoise"; | ||
| case CcpColor::DarkViolet: return "DarkViolet"; | ||
| case CcpColor::DeepPink: return "DeepPink"; | ||
| case CcpColor::DeepSkyBlue: return "DeepSkyBlue"; | ||
| case CcpColor::DimGray: return "DimGray / DimGrey"; | ||
| case CcpColor::DodgerBlue: return "DodgerBlue"; | ||
| case CcpColor::FireBrick: return "FireBrick"; | ||
| case CcpColor::FloralWhite: return "FloralWhite"; | ||
| case CcpColor::ForestGreen: return "ForestGreen"; | ||
| case CcpColor::Fuchsia: return "Fuchsia / Magenta"; | ||
| case CcpColor::Gainsboro: return "Gainsboro"; | ||
| case CcpColor::GhostWhite: return "GhostWhite"; | ||
| case CcpColor::Gold: return "Gold"; | ||
| case CcpColor::Goldenrod: return "Goldenrod"; | ||
| case CcpColor::Gray: return "Gray / Grey"; | ||
| case CcpColor::Green: return "Green"; | ||
| case CcpColor::GreenYellow: return "GreenYellow"; | ||
| case CcpColor::Honeydew: return "Honeydew"; | ||
| case CcpColor::HotPink: return "HotPink"; | ||
| case CcpColor::IndianRed: return "IndianRed"; | ||
| case CcpColor::Indigo: return "Indigo"; | ||
| case CcpColor::Ivory: return "Ivory"; | ||
| case CcpColor::Khaki: return "Khaki"; | ||
| case CcpColor::Lavender: return "Lavender"; | ||
| case CcpColor::LavenderBlush: return "LavenderBlush"; | ||
| case CcpColor::LawnGreen: return "LawnGreen"; | ||
| case CcpColor::LemonChiffon: return "LemonChiffon"; | ||
| case CcpColor::LightBlue: return "LightBlue"; | ||
| case CcpColor::LightCoral: return "LightCoral"; | ||
| case CcpColor::LightCyan: return "LightCyan"; | ||
| case CcpColor::LightGoldenrodYellow: return "LightGoldenrodYellow"; | ||
| case CcpColor::LightGray: return "LightGray / LightGrey"; | ||
| case CcpColor::LightGreen: return "LightGreen"; | ||
| case CcpColor::LightPink: return "LightPink"; | ||
| case CcpColor::LightSalmon: return "LightSalmon"; | ||
| case CcpColor::LightSeaGreen: return "LightSeaGreen"; | ||
| case CcpColor::LightSkyBlue: return "LightSkyBlue"; | ||
| case CcpColor::LightSlateGray: return "LightSlateGray / LightSlateGrey"; | ||
| case CcpColor::LightSteelBlue: return "LightSteelBlue"; | ||
| case CcpColor::LightYellow: return "LightYellow"; | ||
| case CcpColor::Lime: return "Lime"; | ||
| case CcpColor::LimeGreen: return "LimeGreen"; | ||
| case CcpColor::Linen: return "Linen"; | ||
| case CcpColor::Maroon: return "Maroon"; | ||
| case CcpColor::MediumAquamarine: return "MediumAquamarine"; | ||
| case CcpColor::MediumBlue: return "MediumBlue"; | ||
| case CcpColor::MediumOrchid: return "MediumOrchid"; | ||
| case CcpColor::MediumPurple: return "MediumPurple"; | ||
| case CcpColor::MediumSeaGreen: return "MediumSeaGreen"; | ||
| case CcpColor::MediumSlateBlue: return "MediumSlateBlue"; | ||
| case CcpColor::MediumSpringGreen: return "MediumSpringGreen"; | ||
| case CcpColor::MediumTurquoise: return "MediumTurquoise"; | ||
| case CcpColor::MediumVioletRed: return "MediumVioletRed"; | ||
| case CcpColor::MidnightBlue: return "MidnightBlue"; | ||
| case CcpColor::MintCream: return "MintCream"; | ||
| case CcpColor::MistyRose: return "MistyRose"; | ||
| case CcpColor::Moccasin: return "Moccasin"; | ||
| case CcpColor::NavajoWhite: return "NavajoWhite"; | ||
| case CcpColor::Navy: return "Navy"; | ||
| case CcpColor::OldLace: return "OldLace"; | ||
| case CcpColor::Olive: return "Olive"; | ||
| case CcpColor::OliveDrab: return "OliveDrab"; | ||
| case CcpColor::Orange: return "Orange"; | ||
| case CcpColor::OrangeRed: return "OrangeRed"; | ||
| case CcpColor::Orchid: return "Orchid"; | ||
| case CcpColor::PaleGoldenrod: return "PaleGoldenrod"; | ||
| case CcpColor::PaleGreen: return "PaleGreen"; | ||
| case CcpColor::PaleTurquoise: return "PaleTurquoise"; | ||
| case CcpColor::PaleVioletRed: return "PaleVioletRed"; | ||
| case CcpColor::PapayaWhip: return "PapayaWhip"; | ||
| case CcpColor::PeachPuff: return "PeachPuff"; | ||
| case CcpColor::Peru: return "Peru"; | ||
| case CcpColor::Pink: return "Pink"; | ||
| case CcpColor::Plum: return "Plum"; | ||
| case CcpColor::PowderBlue: return "PowderBlue"; | ||
| case CcpColor::Purple: return "Purple"; | ||
| case CcpColor::RebeccaPurple: return "RebeccaPurple"; | ||
| case CcpColor::Red: return "Red"; | ||
| case CcpColor::RosyBrown: return "RosyBrown"; | ||
| case CcpColor::RoyalBlue: return "RoyalBlue"; | ||
| case CcpColor::SaddleBrown: return "SaddleBrown"; | ||
| case CcpColor::Salmon: return "Salmon"; | ||
| case CcpColor::SandyBrown: return "SandyBrown"; | ||
| case CcpColor::SeaGreen: return "SeaGreen"; | ||
| case CcpColor::SeaShell: return "SeaShell"; | ||
| case CcpColor::Sienna: return "Sienna"; | ||
| case CcpColor::Silver: return "Silver"; | ||
| case CcpColor::SkyBlue: return "SkyBlue"; | ||
| case CcpColor::SlateBlue: return "SlateBlue"; | ||
| case CcpColor::SlateGray: return "SlateGray / SlateGrey"; | ||
| case CcpColor::Snow: return "Snow"; | ||
| case CcpColor::SpringGreen: return "SpringGreen"; | ||
| case CcpColor::SteelBlue: return "SteelBlue"; | ||
| case CcpColor::Tan: return "Tan"; | ||
| case CcpColor::Teal: return "Teal"; | ||
| case CcpColor::Thistle: return "Thistle"; | ||
| case CcpColor::Tomato: return "Tomato"; | ||
| case CcpColor::Turquoise: return "Turquoise"; | ||
| case CcpColor::Violet: return "Violet"; | ||
| case CcpColor::Wheat: return "Wheat"; | ||
| case CcpColor::White: return "White"; | ||
| case CcpColor::WhiteSmoke: return "WhiteSmoke"; | ||
| case CcpColor::Yellow: return "Yellow"; | ||
| case CcpColor::YellowGreen: return "YellowGreen"; | ||
| default: return "ColorNotFound"; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,14 @@ | ||
| // Copyright © 2013 CCP ehf. | ||
|
|
||
| #include <array> | ||
| #include <atomic> | ||
| #include <cctype> | ||
| #include <cstdint> | ||
| #include <optional> | ||
| #include <queue> | ||
|
|
||
| #include "include/CCPAssert.h" | ||
| #include "include/CcpMutex.h" | ||
| #include "include/CcpTelemetry.h" | ||
| #include "include/CcpTime.h" | ||
|
|
||
|
|
@@ -83,6 +88,163 @@ namespace | |
| static EventHandlerVector_t s_eventHandlers( "CcpTelemetry/s_eventHandlers" ); | ||
| return s_eventHandlers; | ||
| } | ||
|
|
||
| // ------------------------------- | ||
| // CaptureMask specifics: | ||
| // ------------------------------- | ||
| constexpr size_t CAPTURE_MASKS_MAX{64}; | ||
|
|
||
| CcpMutex s_captureMaskMutex( "CcpTelemetry", "CaptureMaskMutex" ); | ||
|
|
||
| // Fixed size array of registered CaptureMasks. | ||
| std::array<CcpCaptureMaskInfo, CAPTURE_MASKS_MAX> s_registeredCaptureMasks{ | ||
| CcpCaptureMaskInfo{ "core", CcpColor::LightGreen }, // Pre-allocated capture mask for core, should core ever need it. This also solves the problem that legacy `TMCM_GENERAL` and `TMCM_CPP` otherwise cause an off-by-one error. | ||
| CcpCaptureMaskInfo{ "general", CcpColor::SteelBlue }, // legacy definition from TMCM_GENERAL, used to be a bitmask, but can now be treated as index into this array | ||
| CcpCaptureMaskInfo{ "cpp", CcpColor::Yellow }, // legacy value from TMCM_CPP, used to be a bitmask, but can now be treated as index into this array | ||
| }; | ||
|
|
||
| uint64_t s_activeCaptureMaskBits{0}; | ||
|
|
||
|
|
||
| // List of CaptureMask names that have yet to be registered. | ||
| // From a CcpSetActiveCaptureMask( vector<string> ) call. | ||
| std::vector<std::string> s_pendingActiveCaptureMaskNames; | ||
|
CCP-Aporia marked this conversation as resolved.
Outdated
|
||
|
|
||
| // Get the registered CaptureMask color for a given CaptureMask | ||
| CcpColor GetCaptureMaskColor( CcpCaptureMaskHandle handle ) | ||
| { | ||
| return s_registeredCaptureMasks[handle].color; | ||
| } | ||
|
|
||
| bool IsCaptureMaskActive( CcpCaptureMaskHandle handle ) | ||
| { | ||
| return ( s_activeCaptureMaskBits & ( 1ULL<<handle ) ) != 0; | ||
| } | ||
| } | ||
|
|
||
| CcpCaptureMaskHandle CcpRegisterCaptureMask( const std::string& name, CcpColor color ) | ||
| { | ||
| // Guard access to registered CaptureMasks while we add/update a new entry | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This commend is unnecessary. It would be more useful to document the mutex itself rather than this particular lock acquisition and it's context. |
||
| CcpAutoMutex lock( s_captureMaskMutex ); | ||
|
|
||
| if( name.empty() ) | ||
| { | ||
| CCP_LOGERR_CH( s_ch, "Cannot register a CaptureMask without a name" ); | ||
| return 0; | ||
| } | ||
|
|
||
| CcpCaptureMaskHandle handle{0}; | ||
| for( auto& entry : s_registeredCaptureMasks ) | ||
| { | ||
| if (entry.name.empty()) | ||
|
CCP-Aporia marked this conversation as resolved.
Outdated
|
||
| { | ||
| entry.name = name; | ||
| entry.color = color; | ||
| CCP_LOG_CH( s_ch, "Registered a new CaptureMask for '%s' -> %u with color %s", name.c_str(), handle, CcpColorToString( color ).data() ); | ||
| break; | ||
| } | ||
| ++handle; | ||
| } | ||
|
|
||
| if ( handle > CAPTURE_MASKS_MAX ) | ||
| { | ||
| return CCP_CAPTURE_MASK_INVALID_HANDLE; | ||
| } | ||
|
|
||
| // Make sure previously "pending active" CaptureMask is included | ||
| auto pendingIt = std::find( s_pendingActiveCaptureMaskNames.begin(), s_pendingActiveCaptureMaskNames.end(), name ); | ||
| if( pendingIt != s_pendingActiveCaptureMaskNames.end() ) | ||
| { | ||
| s_pendingActiveCaptureMaskNames.erase( pendingIt ); | ||
| s_activeCaptureMaskBits |= ( 1ULL << handle ); | ||
| CCP_LOG_CH( s_ch, "Previously pending CaptureMask '%s' added to activeCaptureMask -> %u", name.c_str(), handle ); | ||
| } | ||
|
|
||
| return handle; | ||
| } | ||
|
|
||
| std::vector<CcpCaptureMaskInfo> CcpGetRegisteredCaptureMasks() | ||
| { | ||
| // Guard access to registered CaptureMasks while return list is populated. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| CcpAutoMutex lock( s_captureMaskMutex ); | ||
|
|
||
| std::vector<CcpCaptureMaskInfo> result; | ||
| result.reserve( CAPTURE_MASKS_MAX ); | ||
| for( const auto& registeredEntry : s_registeredCaptureMasks ) | ||
| { | ||
| if( ! registeredEntry.name.empty() ) | ||
|
CCP-Aporia marked this conversation as resolved.
Outdated
|
||
| { | ||
| result.push_back( registeredEntry ); | ||
| } | ||
| } | ||
| return result; | ||
| } | ||
|
|
||
| bool CcpSetCaptureMask( const std::vector<std::string>& maskNames ) | ||
| { | ||
| // Guard access to all CaptureMasks members | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| CcpAutoMutex lock( s_captureMaskMutex ); | ||
|
|
||
| if ( maskNames.size() > CAPTURE_MASKS_MAX ) | ||
| { | ||
| CCP_LOGERR_CH( s_ch, "Failed setting active capture mask because more %lu maskNames were passed in, but only %lu are allowed", maskNames.size(), CAPTURE_MASKS_MAX ); | ||
| return false; | ||
| } | ||
|
|
||
| s_pendingActiveCaptureMaskNames.clear(); | ||
| uint64_t newActiveCaptureMask = 0; | ||
| for( const auto& rawName : maskNames ) | ||
| { | ||
| if( rawName.empty() ) | ||
|
ccp-serpent marked this conversation as resolved.
Outdated
|
||
| { | ||
| continue; | ||
| } | ||
|
|
||
| bool alreadyRegistered = false; | ||
| size_t index{0}; | ||
| for( const auto& registeredEntry : s_registeredCaptureMasks ) | ||
| { | ||
| if( registeredEntry.name == rawName ) | ||
| { | ||
| newActiveCaptureMask |= (1ULL << index); | ||
| alreadyRegistered = true; | ||
| break; | ||
| } | ||
| ++index; | ||
| } | ||
|
|
||
| // This CaptureMask hasn't been registered (yet) so add it to the pending list | ||
| if( !alreadyRegistered ) | ||
| { | ||
| if( std::find( s_pendingActiveCaptureMaskNames.begin(), s_pendingActiveCaptureMaskNames.end(), rawName ) == s_pendingActiveCaptureMaskNames.end() ) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the reasoning for not immediately registering the capture mask prior to setting the active capture mask?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
| { | ||
| s_pendingActiveCaptureMaskNames.emplace_back( rawName ); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| s_activeCaptureMaskBits = newActiveCaptureMask; | ||
| CCP_LOG_CH( s_ch, "Active CaptureMask set to 0x%llx (%zu pending unresolved name(s))", static_cast<unsigned long long>( newActiveCaptureMask ), s_pendingActiveCaptureMaskNames.size() ); | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| std::vector<std::string> CcpGetActiveCaptureMask() | ||
| { | ||
| std::vector<std::string> result; | ||
| size_t index{0}; | ||
| for ( const auto& registeredEntry : s_registeredCaptureMasks ) | ||
| { | ||
| uint64_t currentMaskBit = 1ULL << index; | ||
|
|
||
| if ( ( s_activeCaptureMaskBits & currentMaskBit ) != 0 ) | ||
| { | ||
| result.push_back( registeredEntry.name ); | ||
| } | ||
|
|
||
| ++index; | ||
| } | ||
| return result; | ||
| } | ||
|
|
||
| bool CcpTelemetryIsConnected() | ||
|
|
@@ -365,7 +527,7 @@ const std::string& CcpTelemetryGetActiveFiber() | |
| return *t_activeFiber; | ||
| } | ||
|
|
||
| TelemetryZone::TelemetryZone( uint32_t ctx, const char* name, const char* filename, uint32_t lineno, CcpColor color ) : m_impl(std::make_unique<Private>()) | ||
| TelemetryZone::TelemetryZone( CcpCaptureMaskHandle handle, const char* name, const char* filename, uint32_t lineno, CcpColor obsolete ) : m_impl(std::make_unique<Private>()) | ||
| { | ||
| if( s_profilerState.load( std::memory_order_acquire ) != ProfilerState::Started ) | ||
| { | ||
|
|
@@ -374,10 +536,13 @@ TelemetryZone::TelemetryZone( uint32_t ctx, const char* name, const char* filena | |
|
|
||
| CCP_ASSERT( filename != nullptr ); | ||
| CCP_ASSERT( name != nullptr ); | ||
|
|
||
| auto color = GetCaptureMaskColor( handle ); | ||
| const int active = IsCaptureMaskActive( handle ); | ||
| auto data = ___tracy_alloc_srcloc( lineno, filename, strlen( filename ), name, strlen( name ), static_cast<uint32_t>( color ) ); | ||
| // CCP_LOG_CH( s_ch, "[Fiber %p] Creating zone %s (%p)", t_activeFiber->c_str(), ret.first->c_str(), this ); | ||
| m_impl->fiber = t_activeFiber; | ||
| m_impl->telemetryContext.emplace( ___tracy_emit_zone_begin_alloc( data, ctx & TMCM_CPP ) ); | ||
| m_impl->telemetryContext.emplace( ___tracy_emit_zone_begin_alloc( data, active ) ); | ||
| } | ||
|
|
||
| TelemetryZone::TelemetryZone( TelemetryZone&& other ) noexcept : m_impl( std::make_unique<Private>() ) | ||
|
|
@@ -419,8 +584,7 @@ void CcpTelemetryEnterZone( void* key, const char* name, const char* filename, u | |
| if( s_profilerState.load( std::memory_order_acquire ) == ProfilerState::Started ) | ||
| { | ||
| t_manuallyTrackedZones.emplace( key ); | ||
| t_activeTaskletZoneStore->second.emplace( TMCM_CPP, name, filename, lineno, CcpColor::Yellow ); | ||
| // CCP_LOG_CH( s_ch, "[Fiber %p] [Store %p] [Zone %p] Enter", t_activeFiber, t_activeTaskletZoneStore, &t_activeTaskletZoneStore->second.top() ); | ||
| t_activeTaskletZoneStore->second.emplace( TMCM_CPP, name, filename, lineno ); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -481,6 +645,25 @@ void CcpRegisterThread( CcpThreadId_t threadId, const char* name ) | |
| { | ||
| } | ||
|
|
||
| CcpCaptureMaskHandle CcpRegisterCaptureMask( const std::string&, CcpColor ) | ||
| { | ||
| return 0; | ||
| } | ||
|
|
||
| std::vector<CcpCaptureMaskInfo> CcpGetRegisteredCaptureMasks() | ||
| { | ||
| return {}; | ||
| } | ||
|
|
||
| bool CcpSetActiveCaptureMask( const std::vector<std::string>& ) | ||
| { | ||
| } | ||
|
|
||
| std::vector<std::string> CcpGetActiveCaptureMask() | ||
| { | ||
| return {}; | ||
| } | ||
|
|
||
| bool CcpStartTelemetry( const char* server, int connectionType, uint32_t maxThreadCount ) | ||
| { | ||
| return false; | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.