UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
FramePro.h
Go to the documentation of this file.
1/*
2Copyright 2019 PureDev Software Limited
3
4Permission to use, copy, modify, and/or distribute this software for any
5purpose with or without fee is hereby granted, provided that the above
6copyright notice and this permission notice appear in all copies.
7
8THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15*/
16
17//------------------------------------------------------------------------
18//
19// FramePro.h
20//
21//------------------------------------------------------------------------
22/*
23 FramePro
24 Version: 1.10.10.0
25*/
26//------------------------------------------------------------------------
27#ifndef FRAMEPRO_H_INCLUDED
28#define FRAMEPRO_H_INCLUDED
29
30//------------------------------------------------------------------------
31// *** enable/disable FramePro here
32//@EPIC BEGIN: Enable through minimal config file, and enable for engine / game, not external tools
34//@EPIC END
35
36//------------------------------------------------------------------------
37// Scroll down for detailed documentation on all of these macros.
38#if FRAMEPRO_ENABLED
39
40 // session macros
41 #define FRAMEPRO_FRAME_START() FramePro::FrameStart()
42 #define FRAMEPRO_SHUTDOWN() FramePro::Shutdown()
43 #define FRAMEPRO_SET_PORT(port) FramePro::SetPort(port)
44 #define FRAMEPRO_SESSION_INFO(name, value) FramePro::SendSessionInfo(name, value)
45 #define FRAMEPRO_SET_ALLOCATOR(p_allocator) FramePro::SetAllocator(p_allocator)
46 #define FRAMEPRO_SET_THREAD_NAME(name) FramePro::SetThreadName(name)
47 #define FRAMEPRO_SET_THREAD_ID_NAME(thread_id, name) FramePro::SetThreadName(thread_id, name)
48 #define FRAMEPRO_THREAD_ORDER(thread_name) FramePro::SetThreadOrder(FramePro::RegisterString(thread_name))
49 #define FRAMEPRO_REGISTER_STRING(str) FramePro::RegisterString(str)
50 #define FRAMEPRO_START_RECORDING(filename, context_switches, callstacks, max_file_size) FramePro::StartRecording(filename, context_switches, callstacks, max_file_size)
51 #define FRAMEPRO_STOP_RECORDING() FramePro::StopRecording()
52 #define FRAMEPRO_REGISTER_CONNECTION_CHANGED_CALLBACK(callback, context) FramePro::RegisterConnectionChangedCallback(callback, context)
53 #define FRAMEPRO_UNREGISTER_CONNECTION_CHANGED_CALLBACK(callback) FramePro::UnregisterConnectionChangedcallback(callback)
54 #define FRAMEPRO_SET_THREAD_PRIORITY(priority) FramePro::SetThreadPriority(priority)
55 #define FRAMEPRO_SET_THREAD_AFFINITY(affinity) FramePro::SetThreadAffinity(affinity)
56 #define FRAMEPRO_BLOCK_SOCKETS() FramePro::BlockSockets()
57 #define FRAMEPRO_UNBLOCK_SOCKETS() FramePro::UnblockSockets()
58 #define FRAMEPRO_CLEANUP_THREAD() FramePro::CleanupThread()
59 #define FRAMEPRO_THREAD_SCOPE(thread_name) FramePro::ThreadScope framepro_thread_scope(thread_name)
60 #define FRAMEPRO_LOG(message) FramePro::Log(message)
61 #define FRAMEPRO_COLOUR(r, g, b) ((FramePro::uint)((((FramePro::uint)((r)&0xff))<<16) | (((FramePro::uint)((g)&0xff))<<8) | ((b)&0xff)))
62 #define FRAMEPRO_SET_CONDITIONAL_SCOPE_MIN_TIME(microseconds) FramePro::SetConditionalScopeMinTimeInMicroseconds(microseconds)
63
64 // scope macros
65 #define FRAMEPRO_SCOPE() FramePro::TimerScope FRAMEPRO_UNIQUE(timer_scope)(FRAMEPRO_FUNCTION_NAME_LITERAL "|" FRAMEPRO_SOURCE_STRING)
66 #define FRAMEPRO_NAMED_SCOPE(name) FramePro::TimerScope FRAMEPRO_UNIQUE(timer_scope)(name "|" FRAMEPRO_SOURCE_STRING)
67 #define FRAMEPRO_NAMED_SCOPE_W(name) FramePro::TimerScopeW FRAMEPRO_UNIQUE(timer_scope)(name L"|" FRAMEPRO_SOURCE_STRING_W)
68 #define FRAMEPRO_ID_SCOPE(name_id) FramePro::IdTimerScope FRAMEPRO_UNIQUE(timer_scope)(name_id, FRAMEPRO_SOURCE_STRING)
69 #define FRAMEPRO_DYNAMIC_SCOPE(dynamic_string) FramePro::IdTimerScope FRAMEPRO_UNIQUE(timer_scope)(FramePro::IsConnected() ? FramePro::RegisterString(dynamic_string) : -1, FRAMEPRO_SOURCE_STRING)
70 #define FRAMEPRO_CONDITIONAL_SCOPE() FramePro::ConditionalTimerScope FRAMEPRO_UNIQUE(timer_scope)(FRAMEPRO_FUNCTION_NAME_LITERAL "|" FRAMEPRO_SOURCE_STRING)
71 #define FRAMEPRO_CONDITIONAL_ID_SCOPE(name) FramePro::ConditionalTimerScopeId FRAMEPRO_UNIQUE(timer_scope)(name, FRAMEPRO_SOURCE_STRING)
72 #define FRAMEPRO_CONDITIONAL_NAMED_SCOPE(name) FramePro::ConditionalTimerScope FRAMEPRO_UNIQUE(timer_scope)(name "|" FRAMEPRO_SOURCE_STRING)
73 #define FRAMEPRO_CONDITIONAL_NAMED_SCOPE_W(name) FramePro::ConditionalTimerScopeW FRAMEPRO_UNIQUE(timer_scope)(name L"|" FRAMEPRO_SOURCE_STRING_W)
74 #define FRAMEPRO_CONDITIONAL_BOOL_SCOPE(b) FramePro::ConditionalBoolTimerScope FRAMEPRO_UNIQUE(timer_scope)(FRAMEPRO_FUNCTION_NAME_LITERAL "|" FRAMEPRO_SOURCE_STRING, (b))
75 #define FRAMEPRO_CONDITIONAL_BOOL_ID_SCOPE(name, b) FramePro::ConditionalBoolTimerScopeId FRAMEPRO_UNIQUE(timer_scope)(name, FRAMEPRO_SOURCE_STRING, (b))
76 #define FRAMEPRO_CONDITIONAL_BOOL_NAMED_SCOPE(name, b) FramePro::ConditionalBoolTimerScope FRAMEPRO_UNIQUE(timer_scope)(name "|" FRAMEPRO_SOURCE_STRING, (b))
77 #define FRAMEPRO_CONDITIONAL_BOOL_NAMED_SCOPE_W(name, b) FramePro::ConditionalBoolTimerScopeW FRAMEPRO_UNIQUE(timer_scope)(name L"|" FRAMEPRO_SOURCE_STRING_W, (b))
78 #define FRAMEPRO_START_NAMED_SCOPE(name) FramePro::int64 framepro_start_##name=0; MULTI_STATEMENT( if(FramePro::IsConnected()) { FRAMEPRO_GET_CLOCK_COUNT(framepro_start_##name); FramePro::StartScope(); } )
79 #define FRAMEPRO_STOP_NAMED_SCOPE(name) MULTI_STATEMENT( if(FramePro::IsConnected()) { FramePro::int64 framepro_end_##name; FRAMEPRO_GET_CLOCK_COUNT(framepro_end_##name); FramePro::AddTimeSpan(#name "|" FRAMEPRO_SOURCE_STRING, framepro_start_##name, framepro_end_##name); FramePro::StopScope(); } )
80 #define FRAMEPRO_CONDITIONAL_START_SCOPE() FramePro::int64 framepro_start=0; MULTI_STATEMENT( if(FramePro::IsConnected()) { FRAMEPRO_GET_CLOCK_COUNT(framepro_start); FramePro::StartScope(); } )
81 #define FRAMEPRO_CONDITIONAL_STOP_NAMED_SCOPE(name) MULTI_STATEMENT( if(FramePro::IsConnected()) { FramePro::int64 framepro_end; FRAMEPRO_GET_CLOCK_COUNT(framepro_end); if(framepro_end - framepro_start > FramePro::GetConditionalScopeMinTime()) FramePro::AddTimeSpan(name "|" FRAMEPRO_SOURCE_STRING, framepro_start, framepro_end); FramePro::StopScope();} )
82 #define FRAMEPRO_CONDITIONAL_STOP_DYNAMIC_SCOPE(dynamic_string) MULTI_STATEMENT( if(FramePro::IsConnected()) { FramePro::int64 framepro_end; FRAMEPRO_GET_CLOCK_COUNT(framepro_end); if(framepro_end - framepro_start > FramePro::GetConditionalScopeMinTime()) FramePro::AddTimeSpan(FramePro::RegisterString(dynamic_string), FRAMEPRO_SOURCE_STRING, framepro_start, framepro_end); FramePro::StopScope(); } )
83 #define FRAMEPRO_CONDITIONAL_PARENT_SCOPE(name, callback, pre_duration, post_duration) FramePro::ConditionalParentTimerScope FRAMEPRO_UNIQUE(timer_scope)(name, FRAMEPRO_SOURCE_STRING, callback, pre_duration, post_duration)
84 #define FRAMEPRO_SET_SCOPE_COLOUR(name, colour) MULTI_STATEMENT( FramePro::SetScopeColour(FramePro::RegisterString(name), colour); )
85 #define FRAMEPRO_CALLSTACK() FramePro::SendScopeCallstack()
86
87 // idle scope macros
88 #define FRAMEPRO_IDLE_SCOPE() FramePro::TimerScope FRAMEPRO_UNIQUE(timer_scope)(FRAMEPRO_FUNCTION_NAME_LITERAL "|" FRAMEPRO_SOURCE_STRING_IDLE)
89 #define FRAMEPRO_IDLE_NAMED_SCOPE(name) FramePro::TimerScope FRAMEPRO_UNIQUE(timer_scope)(name "|" FRAMEPRO_SOURCE_STRING_IDLE)
90 #define FRAMEPRO_IDLE_NAMED_SCOPE_W(name) FramePro::TimerScopeW FRAMEPRO_UNIQUE(timer_scope)(name L"|" FRAMEPRO_SOURCE_STRING_IDLE_W)
91 #define FRAMEPRO_IDLE_ID_SCOPE(name_id) FramePro::IdTimerScope FRAMEPRO_UNIQUE(timer_scope)(name_id, FRAMEPRO_SOURCE_STRING_IDLE)
92 #define FRAMEPRO_IDLE_DYNAMIC_SCOPE(dynamic_string) FramePro::IdTimerScope FRAMEPRO_UNIQUE(timer_scope)(FramePro::IsConnected() ? FramePro::RegisterString(dynamic_string) : -1, FRAMEPRO_SOURCE_STRING_IDLE)
93 #define FRAMEPRO_IDLE_CONDITIONAL_SCOPE() FramePro::ConditionalTimerScope FRAMEPRO_UNIQUE(timer_scope)(FRAMEPRO_FUNCTION_NAME_LITERAL "|" FRAMEPRO_SOURCE_STRING_IDLE)
94 #define FRAMEPRO_IDLE_CONDITIONAL_ID_SCOPE(name) FramePro::ConditionalTimerScopeId FRAMEPRO_UNIQUE(timer_scope)(name, FRAMEPRO_SOURCE_STRING_IDLE)
95 #define FRAMEPRO_IDLE_CONDITIONAL_NAMED_SCOPE(name) FramePro::ConditionalTimerScope FRAMEPRO_UNIQUE(timer_scope)(name "|" FRAMEPRO_SOURCE_STRING_IDLE)
96 #define FRAMEPRO_IDLE_CONDITIONAL_NAMED_SCOPE_W(name) FramePro::ConditionalTimerScopeW FRAMEPRO_UNIQUE(timer_scope)(name L"|" FRAMEPRO_SOURCE_STRING_IDLE_W)
97 #define FRAMEPRO_IDLE_START_NAMED_SCOPE(name) FramePro::int64 framepro_start_##name=0; if(FramePro::IsConnected()) { FRAMEPRO_GET_CLOCK_COUNT(framepro_start_##name); FramePro::StartScope(); }
98 #define FRAMEPRO_IDLE_STOP_NAMED_SCOPE(name) MULTI_STATEMENT( if(FramePro::IsConnected()) { FramePro::int64 framepro_end_##name; FRAMEPRO_GET_CLOCK_COUNT(framepro_end_##name); FramePro::AddTimeSpan(#name "|" FRAMEPRO_SOURCE_STRING_IDLE, framepro_start_##name, framepro_end_##name); FramePro::StopScope(); } )
99 #define FRAMEPRO_IDLE_CONDITIONAL_START_SCOPE() FramePro::int64 framepro_start=0; MULTI_STATEMENT( if(FramePro::IsConnected()) { FRAMEPRO_GET_CLOCK_COUNT(framepro_start); FramePro::StartScope(); } )
100 #define FRAMEPRO_IDLE_CONDITIONAL_STOP_NAMED_SCOPE(name) MULTI_STATEMENT( if(FramePro::IsConnected()) { FramePro::int64 framepro_end; FRAMEPRO_GET_CLOCK_COUNT(framepro_end); if(framepro_end - framepro_start > FramePro::GetConditionalScopeMinTime()) FramePro::AddTimeSpan(name "|" FRAMEPRO_SOURCE_STRING_IDLE, framepro_start, framepro_end); FramePro::StopScope(); } )
101 #define FRAMEPRO_IDLE_CONDITIONAL_STOP_DYNAMIC_SCOPE(dynamic_string) MULTI_STATEMENT( if(FramePro::IsConnected()) { FramePro::int64 framepro_end; FRAMEPRO_GET_CLOCK_COUNT(framepro_end); if(framepro_end - framepro_start > FramePro::GetConditionalScopeMinTime()) FramePro::AddTimeSpan(FramePro::RegisterString(dynamic_string), FRAMEPRO_SOURCE_STRING_IDLE, framepro_start, framepro_end); FramePro::StopScope(); } )
102
103 // custom stat macros
104 #define FRAMEPRO_CUSTOM_STAT(name, value, graph, unit, colour) MULTI_STATEMENT( if(FramePro::IsConnected()) FramePro::AddCustomStat(name, value, graph, unit, colour); )
105 #define FRAMEPRO_DYNAMIC_CUSTOM_STAT(name, value, graph, unit, colour) MULTI_STATEMENT( if(FramePro::IsConnected()) FramePro::AddCustomStat(FramePro::RegisterString(name), value, FramePro::RegisterString(graph), FramePro::RegisterString(unit), colour); )
106 #define FRAMEPRO_SCOPE_CUSTOM_STAT(name, value, graph, unit, colour) MULTI_STATEMENT( if(FramePro::IsConnected()) FramePro::SetScopeCustomStat(name, value, graph, unit, colour); )
107 #define FRAMEPRO_SET_CUSTOM_STAT_GRAPH(name, graph) MULTI_STATEMENT( FramePro::SetCustomStatGraph(FramePro::RegisterString(name), FramePro::RegisterString(graph)); )
108 #define FRAMEPRO_SET_CUSTOM_STAT_UNIT(name, unit) MULTI_STATEMENT( FramePro::SetCustomStatUnit(FramePro::RegisterString(name), FramePro::RegisterString(unit)); )
109 #define FRAMEPRO_SET_CUSTOM_STAT_COLOUR(name, colour) MULTI_STATEMENT( FramePro::SetCustomStatColour(FramePro::RegisterString(name), colour); )
110
111 // high-res timers
112 #define FRAMEPRO_HIRES_SCOPE(name) FramePro::HiResTimerScope FRAMEPRO_UNIQUE(hires_scope)(name)
113
114 // custom stat timers
115 #define FRAMEPRO_DECL_CUSTOM_STAT_TIMER(name) FramePro::CustomStatTimer g_FrameProCustomStatTimer##name(#name)
116 #define FRAMEPRO_EXTERN_CUSTOM_STAT_TIMER(name) extern FramePro::CustomStatTimer g_FrameProCustomStatTimer##name
117 #define FRAMEPRO_CUSTOM_STAT_TIMER_SCOPE(name) FramePro::CustomStatTimerScope FRAMEPRO_UNIQUE(timer_scope)(g_FrameProCustomStatTimer##name)
118
119 // events
120 #define FRAMEPRO_EVENT(name, colour) FramePro::AddEvent(name, colour)
121
122 // wait events
123 #define FRAMEPRO_WAIT_EVENT_SCOPE(event_id) FramePro::WaitEventScope FRAMEPRO_UNIQUE(timer_scope)((FramePro::int64)event_id)
124 #define FRAMEPRO_TRIGGER_WAIT_EVENT(event_id) FramePro::TriggerWaitEvent((FramePro::int64)event_id);
125#else
126
127 #define FRAMEPRO_FRAME_START() ((void)0)
128 #define FRAMEPRO_SHUTDOWN() ((void)0)
129 #define FRAMEPRO_SET_PORT(port) ((void)0)
130 #define FRAMEPRO_SESSION_INFO(name, id) ((void)0)
131 #define FRAMEPRO_SET_ALLOCATOR(p_allocator) ((void)0)
132 #define FRAMEPRO_SET_THREAD_NAME(name) ((void)0)
133 #define FRAMEPRO_SET_THREAD_ID_NAME(thread_id, name) ((void)0)
134 #define FRAMEPRO_THREAD_ORDER(thread_name) ((void)0)
135 #define FRAMEPRO_REGISTER_STRING(str) 0
136 #define FRAMEPRO_START_RECORDING(filename, context_switches, callstacks, max_file_size) ((void)0)
137 #define FRAMEPRO_STOP_RECORDING() ((void)0)
138 #define FRAMEPRO_REGISTER_CONNECTION_CHANGED_CALLBACK(callback, context) ((void)0)
139 #define FRAMEPRO_UNREGISTER_CONNECTION_CHANGED_CALLBACK(callback) ((void)0)
140 #define FRAMEPRO_SET_THREAD_PRIORITY(priority) ((void)0)
141 #define FRAMEPRO_SET_THREAD_AFFINITY(affinity) ((void)0)
142 #define FRAMEPRO_UNBLOCK_SOCKETS() ((void)0)
143 #define FRAMEPRO_CLEANUP_THREAD() ((void)0)
144 #define FRAMEPRO_THREAD_SCOPE(thread_name) ((void)0)
145 #define FRAMEPRO_LOG(message) ((void)0)
146 #define FRAMEPRO_COLOUR(r, g, b) ((void)0)
147 #define FRAMEPRO_SET_CONDITIONAL_SCOPE_MIN_TIME(microseconds) ((void)0)
148
149 #define FRAMEPRO_SCOPE() ((void)0)
150 #define FRAMEPRO_NAMED_SCOPE(name) ((void)0)
151 #define FRAMEPRO_NAMED_SCOPE_W(name) ((void)0)
152 #define FRAMEPRO_ID_SCOPE(name_id) ((void)name_id)
153 #define FRAMEPRO_DYNAMIC_SCOPE(dynamic_string) ((void)0)
154 #define FRAMEPRO_CONDITIONAL_SCOPE() ((void)0)
155 #define FRAMEPRO_CONDITIONAL_ID_SCOPE(name) ((void)0)
156 #define FRAMEPRO_CONDITIONAL_NAMED_SCOPE(name) ((void)0)
157 #define FRAMEPRO_CONDITIONAL_NAMED_SCOPE_W(name) ((void)0)
158 #define FRAMEPRO_CONDITIONAL_BOOL_SCOPE(b) ((void)0)
159 #define FRAMEPRO_CONDITIONAL_BOOL_ID_SCOPE(name, b) ((void)0)
160 #define FRAMEPRO_CONDITIONAL_BOOL_NAMED_SCOPE(name, b) ((void)0)
161 #define FRAMEPRO_CONDITIONAL_BOOL_NAMED_SCOPE_W(name, b) ((void)0)
162 #define FRAMEPRO_START_NAMED_SCOPE(name) ((void)0)
163 #define FRAMEPRO_STOP_NAMED_SCOPE(name) ((void)0)
164 #define FRAMEPRO_CONDITIONAL_START_SCOPE() ((void)0)
165 #define FRAMEPRO_CONDITIONAL_STOP_NAMED_SCOPE(name) ((void)0)
166 #define FRAMEPRO_CONDITIONAL_STOP_DYNAMIC_SCOPE(dynamic_string) ((void)0)
167 #define FRAMEPRO_CONDITIONAL_PARENT_SCOPE(name, callback, pre_duration, post_duration) ((void)0)
168 #define FRAMEPRO_SET_SCOPE_COLOUR(name, colour) ((void)0)
169 #define FRAMEPRO_CALLSTACK() ((void)0)
170
171 #define FRAMEPRO_IDLE_SCOPE() ((void)0)
172 #define FRAMEPRO_IDLE_NAMED_SCOPE(name) ((void)0)
173 #define FRAMEPRO_IDLE_NAMED_SCOPE_W(name) ((void)0)
174 #define FRAMEPRO_IDLE_ID_SCOPE(name_id) ((void)name_id)
175 #define FRAMEPRO_IDLE_DYNAMIC_SCOPE(dynamic_string) ((void)0)
176 #define FRAMEPRO_IDLE_CONDITIONAL_SCOPE() ((void)0)
177 #define FRAMEPRO_IDLE_CONDITIONAL_ID_SCOPE(name) ((void)0)
178 #define FRAMEPRO_IDLE_CONDITIONAL_NAMED_SCOPE(name) ((void)0)
179 #define FRAMEPRO_IDLE_CONDITIONAL_NAMED_SCOPE_W(name) ((void)0)
180 #define FRAMEPRO_IDLE_START_NAMED_SCOPE(name) ((void)0)
181 #define FRAMEPRO_IDLE_STOP_NAMED_SCOPE(name) ((void)0)
182 #define FRAMEPRO_IDLE_CONDITIONAL_START_SCOPE() ((void)0)
183 #define FRAMEPRO_IDLE_CONDITIONAL_STOP_NAMED_SCOPE(name) ((void)0)
184 #define FRAMEPRO_IDLE_CONDITIONAL_STOP_DYNAMIC_SCOPE(dynamic_string) ((void)0)
185
186 #define FRAMEPRO_CUSTOM_STAT(name, value, graph, unit, colour) ((void)0)
187 #define FRAMEPRO_DYNAMIC_CUSTOM_STAT(name, value, graph, unit, colour) ((void)0)
188 #define FRAMEPRO_SCOPE_CUSTOM_STAT(name, value, graph, unit, colour) ((void)0)
189 #define FRAMEPRO_SET_CUSTOM_STAT_GRAPH(name, graph) ((void)0)
190 #define FRAMEPRO_SET_CUSTOM_STAT_UNIT(name, unit) ((void)0)
191 #define FRAMEPRO_SET_CUSTOM_STAT_COLOUR(name, colour) ((void)0)
192
193 #define FRAMEPRO_HIRES_SCOPE(name) ((void)0)
194
195 #define FRAMEPRO_DECL_CUSTOM_STAT_TIMER(name)
196 #define FRAMEPRO_EXTERN_CUSTOM_STAT_TIMER(name)
197 #define FRAMEPRO_CUSTOM_STAT_TIMER_SCOPE(name) ((void)0)
198
199 #define FRAMEPRO_EVENT(name, colour) ((void)0)
200
201 #define FRAMEPRO_WAIT_EVENT_SCOPE(event_id) ((void)0)
202 #define FRAMEPRO_TRIGGER_WAIT_EVENT(event_id) ((void)0)
203#endif
204
205//------------------------------------------------------------------------
206// StringId typedef always needs to be defined
207namespace FramePro
208{
209 typedef long long StringId;
210}
211
212//------------------------------------------------------------------------
213// General defines
214
215//------------------------------------------------------------------------
216// Set this to zero if you don't want anyone to be able to connect with FramePro.
217// Recording to a file from code is sill supported.
218#define FRAMEPRO_SOCKETS_ENABLED 1
219
220//------------------------------------------------------------------------
221// Thread local storage buffers are flushed every 30 ms by default. You shouldn't need to change this.
222#define FRAMEPRO_MAX_SEND_DELAY 30
223
224//------------------------------------------------------------------------
225// Write the network data out to a file. Only useful for debugging network issues.
226#define FRAMEPRO_DEBUG_TCP 0
227
228//------------------------------------------------------------------------
229// FramePro will attempt to keep below this amount of memory. If the memory limit
230// is reached it will stall your game. Nothing is pre-allocated, so FramePro will
231// only use up as much mmeory as it needs, which depends on how many scopes are
232// being sent per frame.
233#define FRAMEPRO_MAX_MEMORY (50*1024*1024)
234
235//------------------------------------------------------------------------
236// For added security you can set this to true to disable all networking unless explicitly
237// enabled from code using the FRAMEPRO_UNBLOCK_SOCKETS() macro. In general, it's best to completely
238// define out FramePro with the FRAMEPRO_ENABLED define for retail builds.
239#define FRAMEPRO_SOCKETS_BLOCKED_BY_DEFAULT false
240
241//------------------------------------------------------------------------
242// Never send scopes shorter than this. Undefine to send all scopes.
243#define FRAMEPRO_SCOPE_MIN_TIME 10 // ns
244
245//------------------------------------------------------------------------
246// In order to not flood the channel with wait events of zero length, the event
247// is only sent if it is longer than this value
248#define FRAMEPRO_WAIT_EVENT_MIN_TIME 10 // ns
249
250//------------------------------------------------------------------------
251#define FRAMEPRO_ENABLE_CONTEXT_SWITCH_TRACKING 1
252
253//------------------------------------------------------------------------
254#define FRAMEPRO_ENABLE_CALLSTACKS 0
255
256//------------------------------------------------------------------------
257// If this is disabled and two dynamic strings happen to hash to the same value you may see
258// incorrect strings in the FramePro app. Enabling this does add significant overhead
259// to RegisterString. It is a good idea to use the string literal macros wherever possible
260// which don't call RegiserString anyway.
261#define FRAMEPRO_DETECT_HASH_COLLISIONS 0
262
263//------------------------------------------------------------------------
264#define FRAMEPRO_STACK_TRACE_SIZE 128
265
266//------------------------------------------------------------------------
267// FramePro will assert if a hires scope doesn't have a parent scope. Enabling
268// this define make the code detect that case and throw the hires scope away
269// instead of asserting.
270// This adds extra overhead to all scopes (function calls to increment/decrement
271// on each start/end scope) and so if off by default
272#define FRAMEPRO_ALLOW_UNPARENTED_HIRES_SCOPES 0
273
274//------------------------------------------------------------------------
275// DOCUMENTATION
276//------------------------------------------------------------------------
277
278// Setup
279// -----
280// Please see the setup guide in the help documentation or online, or the setup video for
281// full instructions on setting up FramePro.
282//
283
284// Overview
285// --------
286// The scope macros are designed to have minimal overhead. Sending a scope to FramePro requires
287// recording the start and end time of the scope and sending a string for the scope name. In order
288// to avoid having to send strings across the network, FramePro only sends string ids. For string
289// literals the id is the same as the string pointer and no further work needs to be done. The
290// FramePro app will do the lookup and request the string value if necessary. For synamic strings
291// the string has to be looked up in a hash map. For this reason it is always preferable to use
292// the string literal versions of the macros.
293
294// To send a scope the scope data (start, end, name_id) is copied to a thread local storage buffer.
295// This means that there is no locking involved. The thread local storage buffers are flushed to the
296// socket and sent across the network once every 30ms.
297
298// Summary: Recording and sending a scope consists of grabbing the scope start and end time and copying
299// those to a TLS buffer along with the name id (typically the string literal pointer) - and that's it!
300// No locking, no hashmap lookups, minimal overhead.
301
302// Platforms
303// ---------
304// FramePro supports many platforms, including Windows, Linux, XboxOne, PS4, UE4.
305// If you need to add a platform please implement the functions in the Platform namespace (see FrameProPlatform.h)
306// You will also need to define the platform specific defines in FrameProPlatform.h
307// There are generic utility functions for Windows nad Linux in GenericPlatform that you can use.
308// You can use EventTraceWin32 for context switch recording on windows based platforms.
309// All platform specific code is in FrameProPlatform.cpp/h (or the end of the combined FramePro.cpp file)
310//
311// Proprietary comsole code is split out into seperate files, eg, FrameProPS4.cpp/h.
312// Please contact slynch@puredevsoftware.com for these files.
313//
314
315
316// Definitions
317// -----------
318// string literal: Normal C++ definition. A hard coded string value, for example "my_string"
319// dynamic string: A string built at run-time, for example std::string my_string = string1 + string2;
320// Scope: Normal meaning in the C++ context. A FramePro Scope is a struct that has a start/end time
321// and a name and appears in the thread and core views.
322// Session: A single profile. This can be either connected and the session data is sent to FramePro in realtime,
323// or the session can be recorded to a file.
324// Recording: The session data is written out to a file instead of being sent to FramePro over
325// the network.
326// Conditional scope: A scope that is only sent if the duration is above a threshold
327// Dynamic scope: A scope that takes a dynamic string as an argument (most macros only take string literals)
328
329
330//--------------------------------------------------------------------------------------------------------
331// Session Macros
332//
333// Session macros are macros that give general information about the session and threads, and
334// start/stop recording sessions. The only macros that is required by FramePro is the FRAMEPRO_FRAME_START.
335// It is also advised to set the thread name for each thread which is created.
336
337
338// FRAMEPRO_FRAME_START()
339// ----------------------
340// This must be called at the start of each frame. It tells FramePro when the old frame ends and the new frame starts
341
342
343// FRAMEPRO_SHUTDOWN()
344// -------------------
345// Cleans up all FramePro resources. No thread can call into FramePro after this is called.
346
347
348// FRAMEPRO_SESSION_INFO(name, value)
349// ----------------------------------
350// name: string
351// value: string
352// The name/value pair will be displayed in the FramePro SessionInfo panel. Use it for things such as the build name, version, etc.
353
354
355// FRAMEPRO_SET_ALLOCATOR(p_allocator)
356// -----------------------------------
357// p_allocator: FramePro::Allocator*
358// Set the allocator that FramePro will use to allocate memory. This must be a class inherited from the FramePro::Allocator base class.
359// The allocator class that you provide must be thread safe.
360// NOTE: Call this before calling any other FramePro macro.
361
362
363// FRAMEPRO_SET_THREAD_NAME(name)
364// -----------------------------------------
365// name: string (literal or dynamic)
366// Tell FramePro the name of the current thread.
367// FramePro will pick a colour based on the thread name which will always stay the same.
368
369
370// FRAMEPRO_SET_THREAD_ID_NAME(thread_id, name)
371// -----------------------------------------
372// thread_id: id of the thread to set
373// name: string (literal or dynamic)
374// Tell FramePro the name of the specified thread.
375// FramePro will pick a colour based on the thread name which will always stay the same.
376
377
378// FRAMEPRO_THREAD_ORDER(thread_name)
379// ----------------------------------
380// thread_name: string (literal or dynamic)
381// To keep the order of the threads in the thread view consistent for all users you can specify the thread ordering
382// from your game. The threads will appear in the order that the macros are called. For example:
383// FRAMEPRO_THREAD_ORDER("MainThread");
384// FRAMEPRO_THREAD_ORDER("RenderTHread");
385// FRAMEPRO_THREAD_ORDER("WorkerThread1");
386// FRAMEPRO_THREAD_ORDER("WorkerThread2");
387// FRAMEPRO_THREAD_ORDER("WorkerThread3");
388// FRAMEPRO_THREAD_ORDER("WorkerThread4");
389
390
391// FRAMEPRO_REGISTER_STRING(str)
392// -----------------------------
393// str: string (dynamic)
394// returns: FramePro::StringId
395// Passing in dynamic strings to scope macros is costly because the string has to be looked up ni a hashmap to
396// determine if it needs to send the string value to FramePro. for dynamic strings that never change (for example
397// the name of an entity) you can cache off the string id (in the entity) using this macro and pass that in to the
398// scope instead of the string.
399
400
401// FRAMEPRO_START_RECORDING(filename, context_switches, callstacks, max_file_size)
402// -------------------------------------------------------------------
403// filename: string - the filename to write the recording out to. Extension should be .framepro_recording
404// context_switches: bool - whether to record context switches
405// callstacks: bool - true to record the callstack of each scope. Warning, can negatively affect performance if you have a lot of scopes
406// max_file_size: stop recording once the file reaches this size
407// Instead of connecting to your game with FramePro you can instead write all of the network data out to a file.
408// This recording file can then be loaded in FramePro. This can be useful if you want to start/stop a recording
409// at a specific point in code, or if you want to automate the profiling session capture.
410// If a recording was already started that recording will be stopped and this recording will be started.
411// Connections from FramePro are disabled while a recording is in progress.
412
413
414// FRAMEPRO_STOP_RECORDING()
415// -------------------------
416// Stop a recording started with FRAMEPRO_START_RECORDING.
417
418
419// FRAMEPRO_REGISTER_CONNECTION_CHANGED_CALLBACK(callback, p_recording_filename, context)
420// --------------------------------------------------------------------------------------
421// callback: ConnectionChangedCallback function pointer
422// context: void*
423// Add a callback to be called when a connection is made or lost.
424// context is passed in to the callback as user_data.
425// The callback is of the form:
426// typedef void (*ConnectionChangedCallback)(bool connected, const wchar_t* p_recording_filename, void* user_data);
427// If already connected the callback will be called immediately.
428// Multiple callbacks can be registered.
429
430
431// FRAMEPRO_UNREGISTER_CONNECTION_CHANGED_CALLBACK(callback)
432// ---------------------------------------------------------
433// Unregister a callback that was registered with FRAMEPRO_REGISTER_CONNECTION_CHANGED_CALLBACK
434
435
436// FRAMEPRO_SET_THREAD_PRIORITY(priority)
437// --------------------------------------
438// priority: int
439// Tell FramePro the priority of a thread. This will be displayed in the thread information (hover over the thread panel)
440// It is often useful to be able to see the thread priorities in FramePro when looking at core usage.
441
442
443// FRAMEPRO_SET_THREAD_AFFINITY(affinity)
444// --------------------------------------
445// affinity: int
446// Tell FramePro the affinity of a thread. This will be displayed in the thread information (hover over the thread panel)
447// It is often useful to be able to see the thread priorities in FramePro when looking at core usage.
448
449
450// FRAMEPRO_UNBLOCK_SOCKETS()
451// --------------------------
452// As a security measure you can define FRAMEPRO_SOCKETS_BLOCKED_BY_DEFAULT to true. This will disable all network
453// access by default. You can then call FRAMEPRO_UNBLOCK_SOCKETS() to explicitly allow connections.
454
455
456// FRAMEPRO_CLEANUP_THREAD()
457// --------------------------
458// Call from a thread just before it exits to free the memory allocated for this thread. Do not call any other
459// FramePro macros from the thread after calling this. FRAMEPRO_SHUTDOWN will automatically call this on all
460// threads, so usually you don't need to call this. It is only necessary for threads that are created and destroyed.
461// Note: Make sure that you don't call this inside a FramePro scope.
462// during the session.
463
464
465// FRAMEPRO_THREAD_SCOPE(thread_name)
466// ----------------------------------
467// thread_name: string (literal or dynamic)
468// Calls FRAMEPRO_SET_THREAD_NAME at the start of the scope, and FRAMEPRO_CLEANUP_THREAD at the end of the scope.
469// Ensure that this is called outside of any other scopes.
470
471
472// FRAMEPRO_LOG(message)
473// ---------------------
474// message: string (literal or dynamic)
475// Send a log message to FramePro. All log messages are timestamped.
476
477
478
479
480
481//--------------------------------------------------------------------------------------------------------
482// scope macros
483
484
485// FRAMEPRO_SCOPE()
486// ----------------
487// Starts a timer immediately and stops it when the current scope ends. The scope name will be the function name.
488// This is typically the most used scope. Put it at the start of a function.
489// This macro has minimal overhead.
490
491
492// FRAMEPRO_NAMED_SCOPE(name)
493// --------------------------
494// name: string - NOTE: MUST be string literal
495// Starts a timer immediately and stops it when the current scope ends. This macro is used for timing any scope
496// and allows you to explicitly set the scope name.
497// This macro has minimal overhead.
498
499
500// FRAMEPRO_NAMED_SCOPE_W(name)
501// ----------------------------
502// name: wide string - NOTE: MUST be string literal
503// Starts a timer immediately and stops it when the current scope ends. This macro is used for timing any scope
504// and allows you to explicitly set the scope name.
505// This macro has minimal overhead.
506
507
508// FRAMEPRO_ID_SCOPE(name_id)
509// --------------------------
510// name_id: FramePro::StringId
511// Starts a timer immediately and stops it when the current scope ends. This macro is used for timing any scope
512// and allows you to explicitly set the scope name. The name_id is a FramePro string is returned from FRAMEPRO_REGISTER_STRING
513// This macro has minimal overhead.
514
515
516// FRAMEPRO_DYNAMIC_SCOPE(dynamic_string)
517// --------------------------------------
518// dynamic_string: dynamic string
519// Starts a timer immediately and stops it when the current scope ends. This macro is used for timing any scope
520// and allows you to explicitly set the scope name.
521// This macro has medium overhead beacuse it has to create a hash of the string and look it up on a hash map.
522// Only use where absolutely necessary. In general, try and use the string literal or string id versions.
523
524
525// FRAMEPRO_CONDITIONAL_SCOPE()
526// ----------------------------
527// Starts a timer immediately and stops it when the current scope ends. The scope name will be the function name.
528// Put it at the start of a function. The data will only be sent to FramePro if the scope time is greater than the
529// conditional scope threshold. The threshold is set in FramePro using the threshold slider and defaults to 50ms.
530// Conditional scopes scan be useful for scopes that would be too numerous if always sent, but occasionally spike.
531
532
533// FRAMEPRO_CONDITIONAL_ID_SCOPE(name)
534// -----------------------------------
535// name: FramePro::StringId
536// Starts a timer immediately and stops it when the current scope ends. The name of the scope is set explicitly.
537// The data will only be sent to FramePro if the scope time is greater than the conditional scope threshold. The
538// threshold is set in FramePro using the threshold slider and defaults to 50ms.
539// Conditional scopes scan be useful for scopes that would be too numerous if always sent, but occasionally spike.
540
541
542// FRAMEPRO_CONDITIONAL_NAMED_SCOPE(name)
543// --------------------------------------
544// name: string - NOTE: MUST be string literal
545// Starts a timer immediately and stops it when the current scope ends. The name of the scope is set explicitly.
546// The data will only be sent to FramePro if the scope time is greater than the conditional scope threshold. The
547// threshold is set in FramePro using the threshold slider and defaults to 50ms.
548// Conditional scopes scan be useful for scopes that would be too numerous if always sent, but occasionally spike.
549
550
551// FRAMEPRO_CONDITIONAL_NAMED_SCOPE_W(name)
552// --------------------------------------
553// name: string - NOTE: MUST be string literal
554// Starts a timer immediately and stops it when the current scope ends. The name of the scope is set explicitly.
555// The data will only be sent to FramePro if the scope time is greater than the conditional scope threshold. The
556// threshold is set in FramePro using the threshold slider and defaults to 50ms.
557// Conditional scopes scan be useful for scopes that would be too numerous if always sent, but occasionally spike.
558
559
560// FRAMEPRO_CONDITIONAL_BOOL_SCOPE(b)
561// ----------------------------------
562// b: bool - whether to send the scope or not
563// Starts a timer immediately and stops it when the current scope ends. The scope name will be the function name.
564// Put it at the start of a function. The data will only be sent to FramePro if the scope time is greater than the
565// conditional scope threshold. The threshold is set in FramePro using the threshold slider and defaults to 50ms.
566// Conditional scopes scan be useful for scopes that would be too numerous if always sent, but occasionally spike.
567
568
569// FRAMEPRO_CONDITIONAL_BOOL_ID_SCOPE(name, b)
570// -------------------------------------------
571// b: bool - whether to send the scope or not
572// name: FramePro::StringId
573// Starts a timer immediately and stops it when the current scope ends. The name of the scope is set explicitly.
574// The data will only be sent to FramePro if the scope time is greater than the conditional scope threshold. The
575// threshold is set in FramePro using the threshold slider and defaults to 50ms.
576// Conditional scopes scan be useful for scopes that would be too numerous if always sent, but occasionally spike.
577
578
579// FRAMEPRO_CONDITIONAL_BOOL_NAMED_SCOPE(name, b)
580// ----------------------------------------------
581// b: bool - whether to send the scope or not
582// name: string - NOTE: MUST be string literal
583// Starts a timer immediately and stops it when the current scope ends. The name of the scope is set explicitly.
584// The data will only be sent to FramePro if the scope time is greater than the conditional scope threshold. The
585// threshold is set in FramePro using the threshold slider and defaults to 50ms.
586// Conditional scopes scan be useful for scopes that would be too numerous if always sent, but occasionally spike.
587
588
589// FRAMEPRO_CONDITIONAL_NAMED_BOOL_SCOPE_W(name, b)
590// ------------------------------------------------
591// b: bool - whether to send the scope or not
592// name: string - NOTE: MUST be string literal
593// Starts a timer immediately and stops it when the current scope ends. The name of the scope is set explicitly.
594// The data will only be sent to FramePro if the scope time is greater than the conditional scope threshold. The
595// threshold is set in FramePro using the threshold slider and defaults to 50ms.
596// Conditional scopes scan be useful for scopes that would be too numerous if always sent, but occasionally spike.
597
598
599// FRAMEPRO_START_NAMED_SCOPE(name)
600// --------------------------------------
601// name: string literal without quotes - see comment
602// name: string - NOTE: MUST be string literal
603// Start a named scope. Creates a local variable which stores the start time of the scope.
604// This must be matched by a call to FRAMEPRO_STOP_NAMED_SCOPE with the same name passed in.
605// In general, it is preferable to use the scope marcos that automatically close the scope on exit, but
606// there are occasions when you need to start/sto explicitly. Be careful not to overlap scopes, and be careful
607// to always end the scope that you started. Otherwise you will see strange behavour in the thread stack view
608// in FramePro.
609// The name passed in is a string literal without the quotes, for example FRAMEPRO_START_NAMED_SCOPE(my_scope).
610// This will create a local variable using called framepro_start_my_scope and send the scope using the "my_scope"
611// string literal.
612
613
614// FRAMEPRO_STOP_NAMED_SCOPE(name)
615// -------------------------------
616// name: string literal without quotes - this must be the same name that was passed in to FRAMEPRO_START_NAMED_SCOPE
617// Stop a scope started with FRAMEPRO_START_NAMED_SCOPE
618
619
620// FRAMEPRO_CONDITIONAL_START_SCOPE()
621// ----------------------------------
622// Starts a conditional scope. Note that you can only start one conditional scope per scope.
623// Creates a local variable which stores the scope start time.
624
625
626// FRAMEPRO_CONDITIONAL_STOP_NAMED_SCOPE(name)
627// -------------------------------------------
628// name: string - NOTE: MUST be string literal
629// Stop a scope started with FRAMEPRO_CONDITIONAL_START_SCOPE. The name passed in is the name of the scope.
630// The data will only be sent to FramePro if the scope time is greater than the conditional scope threshold. The
631// threshold is set in FramePro using the threshold slider and defaults to 50ms.
632// Conditional scopes scan be useful for scopes that would be too numerous if always sent, but occasionally spike.
633
634
635// FRAMEPRO_CONDITIONAL_STOP_DYNAMIC_SCOPE(dynamic_string)
636// -------------------------------------------------------
637// name: string - dynamic string
638// Stop a scope started with FRAMEPRO_CONDITIONAL_START_SCOPE. The name passed in is the name of the scope.
639// The data will only be sent to FramePro if the scope time is greater than the conditional scope threshold. The
640// threshold is set in FramePro using the threshold slider and defaults to 50ms.
641// Conditional scopes scan be useful for scopes that would be too numerous if always sent, but occasionally spike.
642// This scope is particularly useful for dynamic strings that are slow to evaluate. The string will only be
643// evaluated if the scope time exceeds the threshold.
644// For example: FRAMEPRO_CONDITIONAL_STOP_DYNAMIC_SCOPE(GetEntityName())
645// Where GetEntityName() is too expensive to call all of the time, but if the scopes takes > 50ms it is worth
646// calling it so that the name shows up in FramePro.
647
648
649// FRAMEPRO_CONDITIONAL_PARENT_SCOPE(name, callback, pre_duration, post_duration)
650// ------------------------------------------------------------------------------
651// name: string literal - unique name of the parent
652// callback: FramePro::ConditionalParentScopeCallback - called at the end of the parent scope. Return true form the callback to send the child scopes.
653// pre_duration: int64 - how long to keep the child scopes if the callback returns false (in micro-sec). When the callback returns true all of these scopes will be sent.
654// post_duration: int64 - how long to keep sending the child scopes after the callback has returned false (in micro-sec)
655// The callback is called at the end of the scope. If the callback returns false
656// the child scopes are not sent, instead they are added to a list. The
657// child scopes are kept on the list for pre_duration us. If the
658// callback reutrns true all of the child scopes for this frame and previous frames are sent,
659// and the child scopes are continued to be sent for post_duration after the callback returns false.
660// Note that nesting conditional parent scopes is not supported.
661
662
663// FRAMEPRO_SET_SCOPE_COLOUR(name, colour)
664// --------------------------------------
665// name: string (literal or dynamic)
666// colour: colour using FRAMEPRO_COLOUR macro
667// Set the colour for a scope. Note this will have no effect if the user has set a custom colour in the UI
668// This is a slow macro, so please only call once, not every frame.
669
670
671// FRAMEPRO_CALLSTACK()
672// --------------------------
673// capture the callstack and send for the current scope
674
675
676//--------------------------------------------------------------------------------------------------------
677// idle scope macros
678
679// All scope macros have an idle scope equivalent. An idle scope shows up as semi-transparent in FramePro.
680// Separate macros were created to avoid having to add the overhead of an extra conditional to each scope.
681// Idle scopes are typically used in Sleep or Event wait calls.
682
683
684// FRAMEPRO_IDLE_SCOPE()
685// ---------------------
686// see FRAMEPRO_SCOPE
687
688// FRAMEPRO_IDLE_NAMED_SCOPE(name)
689// -------------------------------
690// see FRAMEPRO_NAMED_SCOPE
691
692// FRAMEPRO_IDLE_NAMED_SCOPE_W(name)
693// ---------------------------------
694// see FRAMEPRO_NAMED_SCOPE_W
695
696// FRAMEPRO_IDLE_ID_SCOPE(name_id)
697// -------------------------------
698// see FRAMEPRO_ID_SCOPE
699
700// FRAMEPRO_IDLE_DYNAMIC_SCOPE(dynamic_string)
701// -------------------------------------------
702// see FRAMEPRO_DYNAMIC_SCOPE
703
704// FRAMEPRO_IDLE_CONDITIONAL_SCOPE()
705// ---------------------------------
706// see FRAMEPRO_CONDITIONAL_SCOPE
707
708// FRAMEPRO_IDLE_CONDITIONAL_ID_SCOPE()
709// ---------------------------------
710// see FRAMEPRO_CONDITIONAL_SCOPE_ID
711
712// FRAMEPRO_IDLE_CONDITIONAL_NAMED_SCOPE(name)
713// -------------------------------------------
714// see FRAMEPRO_CONDITIONAL_NAMED_SCOPE
715
716// FRAMEPRO_IDLE_CONDITIONAL_NAMED_SCOPE_W(name)
717// ---------------------------------------------
718// see FRAMEPRO_CONDITIONAL_NAMED_SCOPE_W
719
720// FRAMEPRO_IDLE_START_NAMED_SCOPE(name)
721// -------------------------------------
722// see FRAMEPRO_START_NAMED_SCOPE
723
724// FRAMEPRO_IDLE_STOP_NAMED_SCOPE(name)
725// ------------------------------------
726// see FRAMEPRO_STOP_NAMED_SCOPE
727
728// FRAMEPRO_IDLE_CONDITIONAL_START_SCOPE()
729// ---------------------------------------
730// see FRAMEPRO_CONDITIONAL_START_SCOPE
731
732// FRAMEPRO_IDLE_CONDITIONAL_STOP_NAMED_SCOPE(name)
733// ------------------------------------------------
734// see FRAMEPRO_CONDITIONAL_STOP_NAMED_SCOPE
735
736// FRAMEPRO_IDLE_CONDITIONAL_STOP_DYNAMIC_SCOPE(dynamic_string)
737// ------------------------------------------------------------
738// see FRAMEPRO_CONDITIONAL_STOP_DYNAMIC_SCOPE
739
740
741//--------------------------------------------------------------------------------------------------------
742// Custom Stat macros
743
744// Custom Stats are zero'd at the start of the frame and accumulated during the frame. Each stat has an accumulated value
745// and a count.The count is the number of times the stat was added to in a frame. Custom stats are keyed off the name
746// value, which must be unique.The "graph" and "utils" values are only read on the first call for a stat and must stay
747// the same thereafter. Graph is the graph name to display the stats. Multipole stats can be put into the same graph.
748// The Units will show in the y-axis.
749
750// FRAMEPRO_CUSTOM_STAT(name, value, graph, unit, colour)
751// ------------------------------------------------------
752// name: string literal - the name of the custom stat
753// value: int, int64, float, double - value to add to the custom stat
754// graph: string (literal or dynamic) - the name of the graph in which the stat will be shown
755// unit: string (literal or dynamic) - the y-axis unit to be displayed in FramePro, eg "ms", "MB" etc for a custom stat
756// colour: colour using FRAMEPRO_COLOUR macro - the colour of the stat. Use zero for default colour. Note this will have no effect if the user has set a custom colour in the UI
757// Adds value to the custom stat with the specified name
758
759// FRAMEPRO_DYNAMIC_CUSTOM_STAT(name, value, graph, unit, colour)
760// --------------------------------------------------------------
761// name: dynamic string - the name of the custom stat
762// value: int, int64, float, double - value to add to the custom stat
763// graph: string (literal or dynamic) - the name of the graph in which the stat will be shown
764// unit: string (literal or dynamic) - the y-axis unit to be displayed in FramePro, eg "ms", "MB" etc for a custom stat
765// colour: colour using FRAMEPRO_COLOUR macro - the colour of the stat. Use zero for default colour. Note this will have no effect if the user has set a custom colour in the UI
766// Adds value to the custom stat with the specified name
767
768// FRAMEPRO_SCOPE_CUSTOM_STAT(name, value, graph, unit, colour)
769// ------------------------------------------------------------
770// name: string literal or StringId - the name of the custom stat
771// value: int64 - the stat value
772// graph: string (literal or dynamic) - the name of the graph in which the stat will be shown
773// unit: string (literal or dynamic) - the y-axis unit to be displayed in FramePro, eg "ms", "MB" etc for a custom stat
774// colour: colour using FRAMEPRO_COLOUR macro - the colour of the stat. Use zero for default colour. Note this will have no effect if the user has set a custom colour in the UI
775// Add a custom stat to the current scope. This will be displayed in the scope hover box and in the frame graph view
776
777// FRAMEPRO_SET_CUSTOM_STAT_GRAPH(name, graph)
778// -------------------------------------------
779// name: string (literal or dynamic)
780// graph: string (literal or dynamic)
781// Set the name of the graph in which to display the stat.
782
783// FRAMEPRO_SET_CUSTOM_STAT_UNIT(name, unit)
784// -----------------------------------------
785// name: string (literal or dynamic)
786// unit: string (literal or dynamic)
787// Set the y-axis unit to be displayed in FramePro, eg "ms", "MB" etc for a custom stat.
788
789// FRAMEPRO_SET_CUSTOM_STAT_COLOUR(name, colour)
790// ---------------------------------------------
791// name: string (literal or dynamic)
792// colour: colour using FRAMEPRO_COLOUR macro - the colour of the stat. Use zero for default colour. Note this will have no effect if the user has set a custom colour in the UI
793
794
795//--------------------------------------------------------------------------------------------------------
796// hires timers
797
798// FRAMEPRO_HIRES_SCOPE(name)
799// --------------------------
800// name: string literal
801// Adds a hi-res timer for the current scope. Use hires timers as a low overhead timer for events that
802// happen at a high frequency.
803//
804// Hires timers for a scope will be shown below that scope as a percentage of the total scope time. Start
805// and end times are not recorded for hires timers, instead the total time and call count are accumulated
806// for the current scope.
807//
808// For example, hires timer1 accounted for 60% of scope1 and was called 460 times. hires2 accounted
809// for 10% of the time. The other 30% of time is spent in scope1.
810// |---------------------------------------------------------------------------------------|
811// | scope1 |
812// |---------------------------------------------------------------------------------------|
813// | hires1 60% (count: 460) | hires2 10% (count: 80) |
814// |--------------------------------------------------------------------------------|
815//
816// Hires timers are useful when you have something that you want to measure which happens at a very high
817// frequency, such as memory allocations, string operations or updates for lots of entities. Because these
818// sort of events happen so many times during a frame, adding normal scopes would have too much overhead
819// and make the thread graph hard to read. Hires timers have minimal overhead and are clear and easy to see
820// in the thread graph.
821
822
823
824//--------------------------------------------------------------------------------------------------------
825// custom stat timers
826
827// Custom stat timers are very low overhead high resolution timers. A custom stat timer is simply
828// a global timer value that is added to on every CUSTOM_STAT_TIMER_SCOPE. The timer is sent and
829// reset at the end of a frame. Custom stat timers are useful for timing events that happen
830// thousands of timer a frame.
831
832// Usage:
833// // this defines a custom stat timer with name "my_timer"
834// FRAMEPRO_DECL_CUSTOM_STAT_TIMER(my_timer)
835//
836// void MyFunction()
837// {
838// FRAMEPRO_CUSTOM_STAT_TIMER_SCOPE(my_timer)
839// ...
840// }
841
842// FRAMEPRO_DECL_CUSTOM_STAT_TIMER(name)
843// -------------------------------------
844// name: unquoted string the name of the custom stat timer object
845// Declares a custom stat timer with the specified name.
846
847// FRAMEPRO_EXTERN_CUSTOM_STAT_TIMER(name)
848// ---------------------------------------
849// name: unquoted string the name of the custom stat timer object
850// Declares an extern to a custom stat timer with the specified name.
851
852// FRAMEPRO_CUSTOM_STAT_TIMER_SCOPE(name)
853// --------------------------------------
854// name: unquoted string the name of the custom stat timer
855// Times the current scope and adds the value to the specified timer. The timer must have already been declared
856// with FRAMEPRO_DECL_CUSTOM_STAT_TIMER.
857
858
859//--------------------------------------------------------------------------------------------------------
860// events
861
862// FRAMEPRO_EVENT(name)
863// --------------------
864// name: string literal
865// Add a named event which will be added to the timeilne.
866
867
868//--------------------------------------------------------------------------------------------------------
869// wait events
870
871// Wait Events are not to be confused with Events. Wait Events are for measuring mutex or critical section
872// locks. Use these macros to record how long your lock is held for, and who unlocked the event. Wait
873// events will appear in the Cores View.
874
875// FRAMEPRO_WAIT_EVENT_SCOPE(event_id)
876// -----------------------------------
877// event_id: unique identifier for the event (must be castable to int64)
878// The easiest thing to use for the event_id is the this pointer of your Event or critical section class.
879// Measure how long a thread waits on an event. For Win32 Events put this around the WaitForSingleObject
880// call. For Win32 critical sections put this around the EnterCriticalSection call. In order to not flood
881// the channel with events, the wait event is only sent if it is longer than FRAMEPRO_WAIT_EVENT_MIN_TIME.
882
883// FRAMEPRO_TRIGGER_WAIT_EVENT(event_id)
884// ----------------------------------
885// event_id: unique identifier for the event (must be castable to int64).
886// The event_id MUST match the id passed in to FRAMEPRO_WAIT_EVENT_SCOPE.
887// Use the FRAMEPRO_TRIGGER_WAIT_EVENT to tell FramePro that a wait event has been triggered. For Win32
888// events call _before_ the SetEvent call. For Win32 critical sections call just before the LeaveCriticalSection.
889
890
891
892//------------------------------------------------------------------------
893//
894// ---- FramePro private ----
895//
896// In general do not use anything below this point. Stuff is only here in order ot keep everything inlined.
897// The macros cover everything that you should need. Also, sticking to the macros means that FramePro can be
898// completely defined out in retail builds.
899
900//------------------------------------------------------------------------
901#if FRAMEPRO_ENABLED
902
903//------------------------------------------------------------------------
904#include <stdlib.h>
905
906//------------------------------------------------------------------------
907// enable this if you are linking to FramePro.dll
908//#define FRAMEPRO_DLL
909
910//------------------------------------------------------------------------
911// enable debug here to get FramePro asserts
912#ifndef FRAMEPRO_DEBUG
913 #if defined(DEBUG) || defined(_DEBUG)
914 #define FRAMEPRO_DEBUG 1
915 #else
916 #define FRAMEPRO_DEBUG 0
917 #endif
918#endif
919
920//------------------------------------------------------------------------
921#define FRAMEPRO_STRINGIZE(x) FRAMEPRO_STRINGIZE2(x)
922#define FRAMEPRO_STRINGIZE2(x) #x
923
924//------------------------------------------------------------------------
925#define FRAMEPRO_JOIN(a, b) FRAMEPRO_JOIN2(a, b)
926#define FRAMEPRO_JOIN2(a, b) a##b
927#define FRAMEPRO_UNIQUE(a) FRAMEPRO_JOIN(a, __LINE__)
928
929//------------------------------------------------------------------------
930#define FRAMEPRO_WIDESTR(s) FRAMEPRO_WIDESTR2(s)
931#define FRAMEPRO_WIDESTR2(s) L##s
932
933//------------------------------------------------------------------------
934#if defined(__UNREAL__)
935 #define FRAMEPRO_PLATFORM_UE4 1
936 #define FRAMEPRO_PLATFORM_XBOXONE 0
937 #define FRAMEPRO_PLATFORM_UWP 0
938 #define FRAMEPRO_PLATFORM_WIN 0
939 #define FRAMEPRO_PLATFORM_LINUX 0
940 #define FRAMEPRO_PLATFORM_PS4 0
941 #define FRAMEPRO_PLATFORM_ANDROID 0
942#elif defined(_XBOX_ONE) || defined(_DURANGO)
943 #define FRAMEPRO_PLATFORM_UE4 0
944 #define FRAMEPRO_PLATFORM_XBOXONE 1
945 #define FRAMEPRO_PLATFORM_UWP 0
946 #define FRAMEPRO_PLATFORM_WIN 0
947 #define FRAMEPRO_PLATFORM_LINUX 0
948 #define FRAMEPRO_PLATFORM_PS4 0
949 #define FRAMEPRO_PLATFORM_ANDROID 0
950#elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
951 #define FRAMEPRO_PLATFORM_UE4 0
952 #define FRAMEPRO_PLATFORM_XBOXONE 0
953 #define FRAMEPRO_PLATFORM_UWP 1
954 #define FRAMEPRO_PLATFORM_WIN 0
955 #define FRAMEPRO_PLATFORM_LINUX 0
956 #define FRAMEPRO_PLATFORM_PS4 0
957 #define FRAMEPRO_PLATFORM_ANDROID 0
958#elif defined(_WIN32) || defined(_WIN64) || defined(WIN32) || defined(WIN64) || defined(__WIN32__) || defined(__WINDOWS__)
959 #define FRAMEPRO_PLATFORM_UE4 0
960 #define FRAMEPRO_PLATFORM_XBOXONE 0
961 #define FRAMEPRO_PLATFORM_UWP 0
962 #define FRAMEPRO_PLATFORM_WIN 1
963 #define FRAMEPRO_PLATFORM_LINUX 0
964 #define FRAMEPRO_PLATFORM_PS4 0
965 #define FRAMEPRO_PLATFORM_ANDROID 0
966#elif defined(__ORBIS__)
967 #define FRAMEPRO_PLATFORM_UE4 0
968 #define FRAMEPRO_PLATFORM_XBOXONE 0
969 #define FRAMEPRO_PLATFORM_UWP 0
970 #define FRAMEPRO_PLATFORM_WIN 0
971 #define FRAMEPRO_PLATFORM_LINUX 0
972 #define FRAMEPRO_PLATFORM_PS4 1
973 #define FRAMEPRO_PLATFORM_ANDROID 0
974#elif defined(__ANDROID__)
975 #define FRAMEPRO_PLATFORM_UE4 0
976 #define FRAMEPRO_PLATFORM_XBOXONE 0
977 #define FRAMEPRO_PLATFORM_UWP 0
978 #define FRAMEPRO_PLATFORM_WIN 0
979 #define FRAMEPRO_PLATFORM_LINUX 0
980 #define FRAMEPRO_PLATFORM_PS4 0
981 #define FRAMEPRO_PLATFORM_ANDROID 1
982#elif defined(unix) || defined(__unix__) || defined(__unix)
983 #define FRAMEPRO_PLATFORM_UE4 0
984 #define FRAMEPRO_PLATFORM_XBOXONE 0
985 #define FRAMEPRO_PLATFORM_UWP 0
986 #define FRAMEPRO_PLATFORM_WIN 0
987 #define FRAMEPRO_PLATFORM_LINUX 1
988 #define FRAMEPRO_PLATFORM_PS4 0
989 #define FRAMEPRO_PLATFORM_ANDROID 0
990#else
991 #error FramePro platform not defined
992#endif
993
994//------------------------------------------------------------------------
995#define FRAMEPRO_SOURCE_STRING __FILE__ "|" FRAMEPRO_FUNCTION_NAME_LITERAL "|" FRAMEPRO_STRINGIZE(__LINE__) "|"
996#define FRAMEPRO_SOURCE_STRING_W FRAMEPRO_WIDESTR(__FILE__) L"|" FRAMEPRO_WIDESTR(FRAMEPRO_FUNCTION_NAME_LITERAL) L"|" FRAMEPRO_WIDESTR(FRAMEPRO_STRINGIZE(__LINE__)) L"|"
997#define FRAMEPRO_SOURCE_STRING_IDLE __FILE__ "|" FRAMEPRO_FUNCTION_NAME_LITERAL "|" FRAMEPRO_STRINGIZE(__LINE__) "|Idle"
998#define FRAMEPRO_SOURCE_STRING_IDLE_W FRAMEPRO_WIDESTR(__FILE__) L"|" FRAMEPRO_WIDESTR(FRAMEPRO_FUNCTION_NAME_LITERAL) L"|" FRAMEPRO_WIDESTR(FRAMEPRO_STRINGIZE(__LINE__)) L"|Idle"
999
1000//------------------------------------------------------------------------
1001#if FRAMEPRO_DEBUG
1002 #define FRAMEPRO_ASSERT(b) if(!(b)) FramePro::DebugBreak()
1003#else
1004 #define FRAMEPRO_ASSERT(b) ((void)0)
1005#endif
1006
1007//------------------------------------------------------------------------
1008#define FRAMEPRO_UNREFERENCED(s) (void)s
1009
1010//------------------------------------------------------------------------
1011// typedefs
1012namespace FramePro
1013{
1014 typedef long long int64;
1015 typedef unsigned long long uint64;
1016 typedef unsigned int uint;
1017}
1018
1019//------------------------------------------------------------------------
1020#define FRAMEPRO_DEFAULT_COND_SCOPE_MIN_TIME 50
1021
1022//------------------------------------------------------------------------
1023#define FRAMEPRO_MAX_INLINE_STRING_LENGTH 256
1024
1025//------------------------------------------------------------------------
1026namespace FramePro
1027{
1028 typedef int(*ThreadMain)(void*);
1029}
1030
1031//------------------------------------------------------------------------
1032namespace FramePro
1033{
1034 namespace PacketType
1035 {
1036 enum Enum
1037 {
1038 Connect = 0xaabb,
1039 FrameStart,
1040 TimeSpan,
1041 TimeSpanW,
1044 ThreadName,
1064 LogPacket,
1088 };
1089 };
1090}
1091
1092//------------------------------------------------------------------------
1093namespace FramePro
1094{
1095 struct ModulePacket
1096 {
1097 PacketType::Enum m_PacketType;
1100 char m_Sig[16];
1101 int m_Age;
1102 int m_Padding;
1105 };
1106}
1107
1108//------------------------------------------------------------------------
1109namespace FramePro
1110{
1111 namespace Platform
1112 {
1113 enum Enum
1114 {
1115 Windows = 0,
1117 XBoxOne,
1118 Unused,
1119 Linux,
1120 PS4,
1121 Android,
1122 Mac,
1123 iOS,
1124 Switch,
1125 };
1126 }
1127}
1128
1129//------------------------------------------------------------------------
1130// FRAMEPRO_API define
1131#ifndef FRAMEPRO_API
1132 #if defined(FRAMEPRO_DLL_EXPORT)
1133 #define FRAMEPRO_API __declspec(dllexport)
1134 #elif defined(FRAMEPRO_DLL)
1135 #define FRAMEPRO_API __declspec(dllimport)
1136 #else
1137 #define FRAMEPRO_API
1138 #endif
1139#endif
1140
1141//------------------------------------------------------------------------
1142
1143//------------------------------------------------------------------------
1144//
1145// FrameProPlatform.h
1146//
1147#if FRAMEPRO_ENABLED
1148
1149//------------------------------------------------------------------------
1150// ---
1151// --- FRAMEPRO PLATFORM IMPLEMENTATION START ---
1152// ---
1153//------------------------------------------------------------------------
1154
1155//------------------------------------------------------------------------
1156#include <stdarg.h> // IWYU pragma: export
1157#include <time.h> // IWYU pragma: export
1158
1159//------------------------------------------------------------------------
1160// FRAMEPRO_PLATFORM_UE4
1161//------------------------------------------------------------------------
1162#if FRAMEPRO_PLATFORM_UE4
1163
1164 #include "FramePro/FrameProUE4.h" // contact slynch@puredevsoftware.com for this platform
1165
1166//------------------------------------------------------------------------
1167// FRAMEPRO_PLATFORM_WIN
1168//------------------------------------------------------------------------
1169#elif FRAMEPRO_PLATFORM_WIN
1170
1172 #define FRAMEPRO_GET_CLOCK_COUNT(time) time = FramePro_QueryPerformanceCounter()
1173
1174 // Windows or Linux based platform
1175 #define FRAMEPRO_WIN_BASED_PLATFORM 1
1176 #define FRAMEPRO_LINUX_BASED_PLATFORM 0
1177
1178 #define FRAMEPRO_USE_TLS_SLOTS 0
1179
1180 // Port
1181 #define FRAMEPRO_PORT "8428"
1182
1183 // x64 or x32
1184 #if defined(_WIN64) || defined(__LP64__) || defined(__x86_64__) || defined(__ppc64__)
1185 #define FRAMEPRO_X64 1
1186 #else
1187 #define FRAMEPRO_X64 0
1188 #endif
1189
1190 #define FRAMEPRO_MAX_PATH 260
1191
1192 #include <tchar.h>
1193 #define FRAMEPRO_TCHAR _TCHAR
1194
1195 #define MULTI_STATEMENT(s) do { s } while(true,false)
1196
1197 #if !defined(__clang__)
1198 #define FRAMEPRO_FUNCTION_DEFINE_IS_STRING_LITERAL 1
1199 #else
1200 #define FRAMEPRO_FUNCTION_DEFINE_IS_STRING_LITERAL 0
1201 #endif
1202
1203 #define FRAMEPRO_NO_INLINE __declspec(noinline)
1204 #define FRAMEPRO_FORCE_INLINE __forceinline
1205
1206 #define LIMIT_RECORDING_FILE_SIZE 1
1207
1208 #define FRAMEPRO_ALIGN_STRUCT(a)
1209
1210 #define FRAMEPRO_ENUMERATE_ALL_MODULES (FRAMEPRO_X64 && 1)
1211
1212//------------------------------------------------------------------------
1213// FRAMEPRO_PLATFORM_UWP
1214//------------------------------------------------------------------------
1215#elif FRAMEPRO_PLATFORM_UWP
1216
1218 #define FRAMEPRO_GET_CLOCK_COUNT(time) time = FramePro_QueryPerformanceCounter()
1219
1220 // Windows or Linux based platform
1221 #define FRAMEPRO_WIN_BASED_PLATFORM 1
1222 #define FRAMEPRO_LINUX_BASED_PLATFORM 0
1223
1224 #define FRAMEPRO_USE_TLS_SLOTS 0
1225
1226 // Port
1227 #define FRAMEPRO_PORT "8428"
1228
1229 // x64 or x32
1230 #define FRAMEPRO_X64 1
1231
1232 #define FRAMEPRO_MAX_PATH 260
1233
1234 #include <tchar.h>
1235 #define FRAMEPRO_TCHAR _TCHAR
1236
1237 #define MULTI_STATEMENT(s) do { s } while(true,false)
1238
1239 #if !defined(__clang__)
1240 #define FRAMEPRO_FUNCTION_DEFINE_IS_STRING_LITERAL 1
1241 #else
1242 #define FRAMEPRO_FUNCTION_DEFINE_IS_STRING_LITERAL 0
1243 #endif
1244
1245 #define FRAMEPRO_NO_INLINE __declspec(noinline)
1246 #define FRAMEPRO_FORCE_INLINE __forceinline
1247
1248 #define LIMIT_RECORDING_FILE_SIZE 1
1249
1250 #define FRAMEPRO_ALIGN_STRUCT(a)
1251
1252 #define FRAMEPRO_ENUMERATE_ALL_MODULES (FRAMEPRO_X64 && 1)
1253
1254//------------------------------------------------------------------------
1255// FRAMEPRO_PLATFORM_ANDROID
1256//------------------------------------------------------------------------
1257#elif FRAMEPRO_PLATFORM_ANDROID
1258
1259 // this needs to be as fast as possible and inline
1260 #define FRAMEPRO_GET_CLOCK_COUNT(time) \
1261 timespec FRAMEPRO_UNIQUE(ts); \
1262 clock_gettime(CLOCK_MONOTONIC, &FRAMEPRO_UNIQUE(ts)); \
1263 time = FRAMEPRO_UNIQUE(ts).tv_sec * 1000000000LL + FRAMEPRO_UNIQUE(ts).tv_nsec
1264
1265 // Windows or Linux based platform
1266 #define FRAMEPRO_WIN_BASED_PLATFORM 0
1267 #define FRAMEPRO_LINUX_BASED_PLATFORM 1
1268
1269 #define FRAMEPRO_USE_TLS_SLOTS 0
1270
1271 // Port
1272 #define FRAMEPRO_PORT "8428"
1273
1274 // x64 or x32
1275 #if defined(__LP64__) || defined(__x86_64__) || defined(__ppc64__)
1276 #define FRAMEPRO_X64 1
1277 #else
1278 #define FRAMEPRO_X64 0
1279 #endif
1280
1281 #define FRAMEPRO_MAX_PATH 260
1282
1283 #define MULTI_STATEMENT(s) do { s } while(false)
1284
1285 namespace FramePro { typedef char FRAMEPRO_TCHAR; }
1286
1287 #define FRAMEPRO_FUNCTION_DEFINE_IS_STRING_LITERAL 0
1288
1289 #define FRAMEPRO_NO_INLINE
1290 #define FRAMEPRO_FORCE_INLINE inline
1291
1292 #define LIMIT_RECORDING_FILE_SIZE 1
1293
1294 #define FRAMEPRO_ALIGN_STRUCT(a) __attribute__ ((aligned(a)))
1295
1296 #define FRAMEPRO_ENUMERATE_ALL_MODULES (FRAMEPRO_X64 && 1)
1297
1298//------------------------------------------------------------------------
1299// FRAMEPRO_PLATFORM_LINUX
1300//------------------------------------------------------------------------
1301#elif FRAMEPRO_PLATFORM_LINUX
1302
1303 // this needs to be as fast as possible and inline
1304 #define FRAMEPRO_GET_CLOCK_COUNT(time) \
1305 timespec FRAMEPRO_UNIQUE(ts); \
1306 clock_gettime(CLOCK_MONOTONIC, &FRAMEPRO_UNIQUE(ts)); \
1307 time = FRAMEPRO_UNIQUE(ts).tv_sec * 1000000000LL + FRAMEPRO_UNIQUE(ts).tv_nsec
1308
1309 // Windows or Linux based platform
1310 #define FRAMEPRO_WIN_BASED_PLATFORM 0
1311 #define FRAMEPRO_LINUX_BASED_PLATFORM 1
1312
1313 #define FRAMEPRO_USE_TLS_SLOTS 0
1314
1315 // Port
1316 #define FRAMEPRO_PORT "8428"
1317
1318 // x64 or x32
1319 #if defined(__LP64__) || defined(__x86_64__) || defined(__ppc64__)
1320 #define FRAMEPRO_X64 1
1321 #else
1322 #define FRAMEPRO_X64 0
1323 #endif
1324
1325 #define FRAMEPRO_MAX_PATH 260
1326
1327 #define MULTI_STATEMENT(s) do { s } while(false)
1328
1329 namespace FramePro { typedef char FRAMEPRO_TCHAR; }
1330
1331 #define FRAMEPRO_FUNCTION_DEFINE_IS_STRING_LITERAL 0
1332
1333 #define FRAMEPRO_NO_INLINE
1334 #define FRAMEPRO_FORCE_INLINE inline
1335
1336 #define LIMIT_RECORDING_FILE_SIZE 1
1337
1338 #define FRAMEPRO_ALIGN_STRUCT(a) __attribute__ ((aligned(a)))
1339
1340 #define FRAMEPRO_ENUMERATE_ALL_MODULES (FRAMEPRO_X64 && 1)
1341
1342//------------------------------------------------------------------------
1343// FRAMEPRO_PLATFORM_XBOXONE
1344//------------------------------------------------------------------------
1345#elif FRAMEPRO_PLATFORM_XBOXONE
1346
1347 #include "FrameProXboxOne.h" // contact slynch@puredevsoftware.com for this platform
1348
1349//------------------------------------------------------------------------
1350// FRAMEPRO_PLATFORM_PS4
1351//------------------------------------------------------------------------
1352#elif FRAMEPRO_PLATFORM_PS4
1353
1354 #include "FrameProPS4.h" // contact slynch@puredevsoftware.com for this platform
1355
1356#else
1357
1358 #error Platform not defined
1359
1360#endif
1361
1362//------------------------------------------------------------------------
1363// ---
1364// --- FRAMEPRO PLATFORM IMPLEMENTATION END ---
1365// ---
1366//------------------------------------------------------------------------
1367
1368//------------------------------------------------------------------------
1369// check all necessary defines are set
1370
1371#ifndef FRAMEPRO_GET_CLOCK_COUNT
1372 #error Platform must defined FRAMEPRO_GET_CLOCK_COUNT
1373#endif
1374
1375#ifndef FRAMEPRO_PORT
1376 #error Platform must define FRAMEPRO_PORT
1377#endif
1378
1379#ifndef FRAMEPRO_X64
1380 #error Platform must define FRAMEPRO_X64
1381#endif
1382
1383#ifndef MULTI_STATEMENT
1384 #error Platform must define MULTI_STATEMENT
1385#endif
1386
1387#ifndef FRAMEPRO_FUNCTION_DEFINE_IS_STRING_LITERAL
1388 #error Platform must define FRAMEPRO_FUNCTION_DEFINE_IS_STRING_LITERAL
1389#endif
1390
1391#ifndef FRAMEPRO_NO_INLINE
1392 #error Platform must define FRAMEPRO_NO_INLINE
1393#endif
1394
1395#ifndef FRAMEPRO_FORCE_INLINE
1396 #error Platform must define FRAMEPRO_FORCE_INLINE
1397#endif
1398
1399#ifndef FRAMEPRO_USE_TLS_SLOTS
1400 #error Platform must define FRAMEPRO_USE_TLS_SLOTS
1401#endif
1402
1403#ifndef LIMIT_RECORDING_FILE_SIZE
1404 #error Platform must define LIMIT_RECORDING_FILE_SIZE
1405#endif
1406
1407//------------------------------------------------------------------------
1408namespace FramePro
1409{
1410 //------------------------------------------------------------------------
1411 class Allocator;
1412 struct ContextSwitch;
1413 class DynamicString;
1414 struct ModulePacket;
1415 template<typename T> class Array;
1416
1417 //------------------------------------------------------------------------
1418 namespace Platform
1419 {
1420 typedef void (*ContextSwitchCallbackFunction)(const ContextSwitch&, void*);
1421
1422 enum Enum;
1423
1425
1426 void DebugBreak();
1427
1428 int GetCore();
1429
1430 bool GetProcessName(int process_id, char* p_name, int max_name_length);
1431
1432 Platform::Enum GetPlatformEnum();
1433
1435
1437
1439
1441
1443
1445
1446 bool GetStackTrace(void** stack, int& stack_size, unsigned int& hash);
1447
1448 int GetCurrentThreadId();
1449
1450 void DebugWrite(const char* p_string);
1451
1452 void GetLocalTime(tm* p_tm, const time_t *p_time);
1453
1454 int GetCurrentProcessId();
1455
1456 void VSPrintf(char* p_buffer, size_t const buffer_size, const char* p_format, va_list arg_list);
1457
1458 void ToString(int value, char* p_dest, int dest_size);
1459
1460 void CreateLock(void* p_os_lock_mem, int os_lock_mem_size);
1461
1462 void DestroyLock(void* p_os_lock_mem);
1463
1464 void TakeLock(void* p_os_lock_mem);
1465
1466 void ReleaseLock(void* p_os_lock_mem);
1467
1469
1470 void DestroyEvent(void* p_os_event_mem);
1471
1472 void SetEvent(void* p_os_event_mem);
1473
1474 void ResetEvent(void* p_os_event_mem);
1475
1476 int WaitEvent(void* p_os_event_mem, int timeout);
1477
1479
1481
1483
1484 void DestroySocket(void* p_os_socket_mem);
1485
1487
1489
1490 bool BindSocket(void* p_os_socket_mem, const char* p_port);
1491
1493
1494 bool SocketSend(void* p_os_socket_mem, const void* p_buffer, int size, int& bytes_sent);
1495
1496 bool SocketReceive(void* p_os_socket_mem, const void* p_buffer, int size, int& bytes_received);
1497
1498 bool IsSocketValid(const void* p_os_socket_mem);
1499
1500 void HandleSocketError();
1501
1502 bool CreateThread(
1503 void* p_os_thread_mem,
1505 ThreadMain p_thread_main,
1506 void* p_context,
1508
1509 void DestroyThread(void* p_os_thread_mem);
1510
1511 void SetThreadPriority(void* p_os_thread_mem, int priority);
1512
1513 void SetThreadAffinity(void* p_os_thread_mem, int affinity);
1514
1515 bool OpenFileForRead(void* p_os_file_mem, int os_file_mem_size, const char* p_filename);
1516
1517 bool OpenFileForRead(void* p_os_file_mem, int os_file_mem_size, const wchar_t* p_filename);
1518
1519 bool OpenFileForWrite(void* p_os_file_mem, int os_file_mem_size, const char* p_filename);
1520
1521 bool OpenFileForWrite(void* p_os_file_mem, int os_file_mem_size, const wchar_t* p_filename);
1522
1523 void CloseFile(void* p_os_file_mem);
1524
1525 void ReadFromFile(void* p_os_file_mem, void* p_data, size_t size);
1526
1527 void WriteToFile(void* p_os_file_mem, const void* p_data, size_t size);
1528
1529 int GetFileSize(const void* p_os_file_mem);
1530
1532
1533 void* GetTLSValue(uint slot);
1534
1535 void SetTLSValue(uint slot, void* p_value);
1536
1537 void GetRecordingFolder(char* p_path, int max_path_length);
1538 }
1539}
1540
1541//------------------------------------------------------------------------
1542#endif // #if FRAMEPRO_ENABLED
1543#include <atomic>
1544
1545//------------------------------------------------------------------------
1546#if FRAMEPRO_WIN_BASED_PLATFORM
1547 #define FRAMEPRO_FUNCTION_NAME __FUNCSIG__
1548#else
1549 #define FRAMEPRO_FUNCTION_NAME __PRETTY_FUNCTION__
1550#endif
1551
1552//------------------------------------------------------------------------
1553#if FRAMEPRO_FUNCTION_DEFINE_IS_STRING_LITERAL
1554 #define FRAMEPRO_FUNCTION_NAME_LITERAL FRAMEPRO_FUNCTION_NAME
1555#else
1556 #define FRAMEPRO_FUNCTION_NAME_LITERAL "" // FRAMEPRO_FUNCTION_NAME is not a string literal on Linux platforms so we can't combine it with other string literals
1557
1558 // If FRAMEPRO_FUNCTION_NAME is not a string literal it can't be
1559 // concatonated with other string literals so we need to pass in
1560 // the name separately.
1561 #ifdef FRAMEPRO_SCOPE
1562 #undef FRAMEPRO_SCOPE
1563 #define FRAMEPRO_SCOPE() FramePro::StringLiteralNamedTimerScope FRAMEPRO_UNIQUE(timer_scope)(FRAMEPRO_FUNCTION_NAME, FRAMEPRO_SOURCE_STRING)
1564 #endif
1565 #ifdef FRAMEPRO_CONDITIONAL_SCOPE
1566 #undef FRAMEPRO_CONDITIONAL_SCOPE
1567 #define FRAMEPRO_CONDITIONAL_SCOPE() FramePro::StringLiteralNamedConditionalTimerScope FRAMEPRO_UNIQUE(timer_scope)(FRAMEPRO_FUNCTION_NAME, FRAMEPRO_SOURCE_STRING)
1568 #endif
1569 #ifdef FRAMEPRO_IDLE_SCOPE
1570 #undef FRAMEPRO_IDLE_SCOPE
1571 #define FRAMEPRO_IDLE_SCOPE() FramePro::StringLiteralNamedTimerScope FRAMEPRO_UNIQUE(timer_scope)(FRAMEPRO_FUNCTION_NAME, FRAMEPRO_SOURCE_STRING_IDLE)
1572 #endif
1573 #ifdef FRAMEPRO_IDLE_CONDITIONAL_SCOPE
1574 #undef FRAMEPRO_IDLE_CONDITIONAL_SCOPE
1575 #define FRAMEPRO_IDLE_CONDITIONAL_SCOPE() FramePro::StringLiteralNamedConditionalTimerScope FRAMEPRO_UNIQUE(timer_scope)(FRAMEPRO_FUNCTION_NAME, FRAMEPRO_SOURCE_STRING_IDLE)
1576 #endif
1577#endif
1578
1579//------------------------------------------------------------------------
1580namespace FramePro
1581{
1582 FRAMEPRO_API void DebugBreak();
1583
1584 // assume aligned reads/writes < 8 bytes are atomic on all platforms
1585 template<typename T>
1586 class RelaxedAtomic
1587 {
1588 public:
1589 RelaxedAtomic() { static_assert(sizeof(T) <= sizeof(size_t), "bad template arg"); FRAMEPRO_ASSERT((((FramePro::uint64)this) % sizeof(T) == 0)); }
1590 RelaxedAtomic(T value) : m_Value(value) { static_assert(sizeof(T) <= sizeof(size_t), "bad template arg"); FRAMEPRO_ASSERT((((FramePro::uint64)this) % sizeof(T) == 0)); }
1591 void operator=(T value) { m_Value = value; }
1592 operator T() const { return m_Value; }
1593 private:
1594 T m_Value;
1595 };
1596}
1597
1598//------------------------------------------------------------------------
1599// the main FramePro interface
1600namespace FramePro
1601{
1602 // callbacks
1603 typedef void(*ConnectionChangedCallback)(bool connected, const wchar_t* p_recording_filename, void* user_data);
1605
1607
1609
1610 inline bool IsConnected() { return g_Connected; }
1611
1612 inline unsigned int GetConditionalScopeMinTime() { return g_ConditionalScopeMinTime; }
1613
1614 FRAMEPRO_API void Shutdown();
1615
1616 FRAMEPRO_API void SetPort(int port);
1617
1618 FRAMEPRO_API void DebugBreak();
1619
1620 FRAMEPRO_API void SendSessionInfo(const char* p_name, const char* p_value);
1621
1622 FRAMEPRO_API void SendSessionInfo(const wchar_t* p_name, const wchar_t* p_value);
1623
1624 FRAMEPRO_API void SetAllocator(class Allocator* p_allocator); // if you call this you must call it BEFORE any other calls
1625
1626 FRAMEPRO_API void FrameStart(); // call at the start of each of your frames
1627
1628 FRAMEPRO_API void AddTimeSpan(const char* p_name_file_and_line, int64 start_time, int64 end_time);
1629
1630 FRAMEPRO_API void AddTimeSpan(const wchar_t* p_name_file_and_line, int64 start_time, int64 end_time);
1631
1632 FRAMEPRO_API void AddTimeSpan(const char* p_name, const char* p_file_and_line, int64 start_time, int64 end_time);
1633
1634 FRAMEPRO_API void AddTimeSpan(StringId name_id, const char* p_file_and_line, int64 start_time, int64 end_time);
1635
1636 FRAMEPRO_API void AddTimeSpan(StringId name_id, const char* p_file_and_line, int64 start_time, int64 end_time, int thread_id, int core);
1637
1638 FRAMEPRO_API void AddCustomStat(const char* p_name, int value, const char* p_graph, const char* p_unit, uint colour);
1639
1640 FRAMEPRO_API void AddCustomStat(const char* p_name, int64 value, const char* p_graph, const char* p_unit, uint colour);
1641
1642 FRAMEPRO_API void AddCustomStat(const char* p_name, float value, const char* p_graph, const char* p_unit, uint colour);
1643
1644 FRAMEPRO_API void AddCustomStat(const char* p_name, double value, const char* p_graph, const char* p_unit, uint colour);
1645
1646 FRAMEPRO_API void AddCustomStat(const wchar_t* p_name, int value, const wchar_t* p_graph, const wchar_t* p_unit, uint colour);
1647
1648 FRAMEPRO_API void AddCustomStat(const wchar_t* p_name, int64 value, const wchar_t* p_graph, const wchar_t* p_unit, uint colour);
1649
1650 FRAMEPRO_API void AddCustomStat(const wchar_t* p_name, float value, const wchar_t* p_graph, const wchar_t* p_unit, uint colour);
1651
1652 FRAMEPRO_API void AddCustomStat(const wchar_t* p_name, double value, const wchar_t* p_graph, const wchar_t* p_unit, uint colour);
1653
1654 FRAMEPRO_API void AddCustomStat(StringId name, int value, const char* p_graph, const char* p_unit, uint colour);
1655
1656 FRAMEPRO_API void AddCustomStat(StringId name, int64 value, const char* p_graph, const char* p_unit, uint colour);
1657
1658 FRAMEPRO_API void AddCustomStat(StringId name, float value, const char* p_graph, const char* p_unit, uint colour);
1659
1660 FRAMEPRO_API void AddCustomStat(StringId name, double value, const char* p_graph, const char* p_unit, uint colour);
1661
1662 FRAMEPRO_API void AddCustomStat(StringId name, int value, const wchar_t* p_graph, const wchar_t* p_unit, uint colour);
1663
1664 FRAMEPRO_API void AddCustomStat(StringId name, int64 value, const wchar_t* p_graph, const wchar_t* p_unit, uint colour);
1665
1666 FRAMEPRO_API void AddCustomStat(StringId name, float value, const wchar_t* p_graph, const wchar_t* p_unit, uint colour);
1667
1668 FRAMEPRO_API void AddCustomStat(StringId name, double value, const wchar_t* p_graph, const wchar_t* p_unit, uint colour);
1669
1670 FRAMEPRO_API void AddCustomStat(StringId name, int value, StringId graph, StringId unit, uint colour);
1671
1673
1674 FRAMEPRO_API void AddCustomStat(StringId name, float value, StringId graph, StringId unit, uint colour);
1675
1676 FRAMEPRO_API void AddCustomStat(StringId name, double value, StringId graph, StringId unit, uint colour);
1677
1678 FRAMEPRO_API void AddEvent(const char* p_name, uint colour);
1679
1681
1683
1684 FRAMEPRO_API void SetThreadName(const char* p_name);
1685
1686 FRAMEPRO_API void SetThreadName(int thread_id, const char* p_name);
1687
1689
1691
1692 FRAMEPRO_API StringId RegisterString(const wchar_t* p_str);
1693
1695
1697
1698 FRAMEPRO_API void StartRecording(const char* p_filename, bool context_switches, bool callstacks, int64 max_file_size);
1699
1700 FRAMEPRO_API void StartRecording(const wchar_t* p_filename, bool context_switches, bool callstacks, int64 max_file_size);
1701
1702 FRAMEPRO_API void StopRecording();
1703
1704 FRAMEPRO_API void SetThreadPriority(int priority);
1705
1706 FRAMEPRO_API void SetThreadAffinity(int affinity);
1707
1709
1711
1713
1714 FRAMEPRO_API void CleanupThread();
1715
1716 FRAMEPRO_API void PushConditionalParentScope(const char* p_name, int64 pre_duration, int64 post_duration); // durations are in us
1717
1719
1721
1722 FRAMEPRO_API void StartHiResTimer(const char* p_name);
1723
1725
1726 FRAMEPRO_API void Log(const char* p_message);
1727
1728 FRAMEPRO_API void SetScopeCustomStat(const char* p_name, int value, const char* p_graph, const char* p_unit, uint colour);
1729
1730 FRAMEPRO_API void SetScopeCustomStat(const wchar_t* p_name, int value, const wchar_t* p_graph, const wchar_t* p_unit, uint colour);
1731
1733
1734 FRAMEPRO_API void SetScopeCustomStat(const char* p_name, int64 value, const char* p_graph, const char* p_unit, uint colour);
1735
1736 FRAMEPRO_API void SetScopeCustomStat(const wchar_t* p_name, int64 value, const wchar_t* p_graph, const wchar_t* p_unit, uint colour);
1737
1739
1740 FRAMEPRO_API void SetScopeCustomStat(const char* p_name, float value, const char* p_graph, const char* p_unit, uint colour);
1741
1742 FRAMEPRO_API void SetScopeCustomStat(const wchar_t* p_name, float value, const wchar_t* p_graph, const wchar_t* p_unit, uint colour);
1743
1744 FRAMEPRO_API void SetScopeCustomStat(StringId name, float value, StringId graph, StringId unit, uint colour);
1745
1746 FRAMEPRO_API void SetScopeCustomStat(const char* p_name, double value, const char* p_graph, const char* p_unit, uint colour);
1747
1748 FRAMEPRO_API void SetScopeCustomStat(const wchar_t* p_name, double value, const wchar_t* p_graph, const wchar_t* p_unit, uint colour);
1749
1750 FRAMEPRO_API void SetScopeCustomStat(StringId name, double value, StringId graph, StringId unit, uint colour);
1751
1753
1755
1757
1759
1761
1763
1764 FRAMEPRO_API int GetCore();
1765
1766#if FRAMEPRO_DEBUG || FRAMEPRO_ALLOW_UNPARENTED_HIRES_SCOPES
1767 FRAMEPRO_API void StartScope();
1768 FRAMEPRO_API void StopScope();
1769#else
1770 inline void StartScope() {}
1771 inline void StopScope() {}
1772#endif
1773}
1774
1775//------------------------------------------------------------------------
1776// TimerScope
1777namespace FramePro
1778{
1779 //------------------------------------------------------------------------
1780 class Allocator
1781 {
1782 public:
1783 virtual void* Alloc(size_t size) = 0;
1784 virtual void Free(void* p) = 0;
1785 virtual ~Allocator() {}
1786 };
1787
1788 //------------------------------------------------------------------------
1789 class TimerScope
1790 {
1791 public:
1793 {
1794 if (FramePro::IsConnected())
1795 {
1798 FramePro::StartScope();
1799 }
1800 else
1801 {
1802 mp_NameAndSourceInfo = nullptr;
1803 m_StartTime = 0;
1804 }
1805 }
1806
1807 ~TimerScope()
1808 {
1810 {
1811 int64 end_time = 0;
1813 FramePro::AddTimeSpan(mp_NameAndSourceInfo, m_StartTime, end_time);
1814 FramePro::StopScope();
1815 }
1816 }
1817
1818 private:
1819 const char* mp_NameAndSourceInfo;
1821 };
1822
1823 //------------------------------------------------------------------------
1824 class TimerScopeW
1825 {
1826 public:
1827 TimerScopeW(const wchar_t* p_name_and_source_info)
1828 {
1829 if (FramePro::IsConnected())
1830 {
1833 FramePro::StartScope();
1834 }
1835 else
1836 {
1837 mp_NameAndSourceInfo = nullptr;
1838 m_StartTime = 0;
1839 }
1840 }
1841
1842 ~TimerScopeW()
1843 {
1845 {
1846 int64 end_time = 0;
1848 FramePro::AddTimeSpan(mp_NameAndSourceInfo, m_StartTime, end_time);
1849 FramePro::StopScope();
1850 }
1851 }
1852
1853 private:
1854 const wchar_t* mp_NameAndSourceInfo;
1856 };
1857
1858 //------------------------------------------------------------------------
1860 {
1861 public:
1864 {
1865 if (FramePro::IsConnected())
1866 {
1867 mp_Name = p_name;
1869
1870 FramePro::PushConditionalParentScope(p_name, pre_duration, post_duration);
1871
1873
1874 FramePro::StartScope();
1875 }
1876 else
1877 {
1878 mp_Name = nullptr;
1879 mp_SourceInfo = nullptr;
1880 m_StartTime = 0;
1881 }
1882 }
1883
1885 {
1886 if (mp_SourceInfo)
1887 {
1888 int64 end_time = 0;
1890
1891 bool add_children = FramePro::CallConditionalParentScopeCallback(mp_Callback, mp_Name, m_StartTime, end_time);
1892 FramePro::PopConditionalParentScope(add_children);
1893
1894 FramePro::AddTimeSpan(mp_Name, mp_SourceInfo, m_StartTime, end_time);
1895
1896 FramePro::StopScope();
1897 }
1898 }
1899
1900 private:
1901 const char* mp_Name;
1902 const char* mp_SourceInfo;
1904
1906 };
1907
1908 //------------------------------------------------------------------------
1909 class IdTimerScope
1910 {
1911 public:
1912 IdTimerScope(StringId name, const char* p_source_info)
1913 {
1914 if (FramePro::IsConnected())
1915 {
1916 m_Name = name;
1919 FramePro::StartScope();
1920 }
1921 else
1922 {
1923 m_Name = 0;
1924 mp_SourceInfo = nullptr;
1925 m_StartTime = 0;
1926 }
1927 }
1928
1930 {
1931 if(mp_SourceInfo)
1932 {
1933 int64 end_time = 0;
1935 FramePro::AddTimeSpan(m_Name, mp_SourceInfo, m_StartTime, end_time);
1936 FramePro::StopScope();
1937 }
1938 }
1939
1940 private:
1942 const char* mp_SourceInfo;
1944 };
1945
1946 //------------------------------------------------------------------------
1948 {
1949 public:
1950 // p_name must be a string literal
1951 StringLiteralNamedTimerScope(const char* p_name, const char* p_source_info)
1952 {
1953 if (FramePro::IsConnected())
1954 {
1955 mp_Name = p_name;
1958 FramePro::StartScope();
1959 }
1960 else
1961 {
1962 mp_Name = nullptr;
1963 mp_SourceInfo = nullptr;
1964 m_StartTime = 0;
1965 }
1966 }
1967
1969 {
1970 if(mp_SourceInfo)
1971 {
1972 int64 end_time = 0;
1974 FramePro::AddTimeSpan(mp_Name, mp_SourceInfo, m_StartTime, end_time);
1975 FramePro::StopScope();
1976 }
1977 }
1978
1979 private:
1980 const char* mp_Name;
1981 const char* mp_SourceInfo;
1983 };
1984
1985 //------------------------------------------------------------------------
1987 {
1988 public:
1990 {
1991 if (FramePro::IsConnected())
1992 {
1995 FramePro::StartScope();
1996 }
1997 else
1998 {
1999 mp_NameAndSourceInfo = nullptr;
2000 m_StartTime = 0;
2001 }
2002 }
2003
2005 {
2007 {
2008 int64 end_time = 0;
2010 if(end_time - m_StartTime > FramePro::GetConditionalScopeMinTime())
2011 FramePro::AddTimeSpan(mp_NameAndSourceInfo, m_StartTime, end_time);
2012 FramePro::StopScope();
2013 }
2014 }
2015
2016 private:
2017 const char* mp_NameAndSourceInfo;
2019 };
2020
2021 //------------------------------------------------------------------------
2023 {
2024 public:
2025 ConditionalTimerScopeId(StringId name, const char* p_source_info)
2026 {
2027 if (FramePro::IsConnected())
2028 {
2029 m_Name = name;
2032 FramePro::StartScope();
2033 }
2034 else
2035 {
2036 m_Name = 0;
2037 mp_SourceInfo = nullptr;
2038 m_StartTime = 0;
2039 }
2040 }
2041
2043 {
2044 if(mp_SourceInfo)
2045 {
2046 int64 end_time = 0;
2048 if(end_time - m_StartTime > FramePro::GetConditionalScopeMinTime())
2049 FramePro::AddTimeSpan(m_Name, mp_SourceInfo, m_StartTime, end_time);
2050 FramePro::StopScope();
2051 }
2052 }
2053
2054 private:
2056 const char* mp_SourceInfo;
2058 };
2059
2060 //------------------------------------------------------------------------
2062 {
2063 public:
2065 {
2066 if (FramePro::IsConnected())
2067 {
2070 FramePro::StartScope();
2071 }
2072 else
2073 {
2074 mp_NameAndSourceInfo = nullptr;
2075 m_StartTime = 0;
2076 }
2077 }
2078
2080 {
2082 {
2083 int64 end_time = 0;
2085 if(end_time - m_StartTime > FramePro::GetConditionalScopeMinTime())
2086 FramePro::AddTimeSpan(mp_NameAndSourceInfo, m_StartTime, end_time);
2087 FramePro::StopScope();
2088 }
2089 }
2090
2091 private:
2092 const wchar_t* mp_NameAndSourceInfo;
2094 };
2095
2096 //------------------------------------------------------------------------
2098 {
2099 public:
2101 {
2102 if (b && FramePro::IsConnected())
2103 {
2106 FramePro::StartScope();
2107 }
2108 else
2109 {
2110 mp_NameAndSourceInfo = nullptr;
2111 m_StartTime = 0;
2112 }
2113 }
2114
2116 {
2118 {
2119 int64 end_time = 0;
2121 if(end_time - m_StartTime > FramePro::GetConditionalScopeMinTime())
2122 FramePro::AddTimeSpan(mp_NameAndSourceInfo, m_StartTime, end_time);
2123 FramePro::StopScope();
2124 }
2125 }
2126
2127 private:
2128 const char* mp_NameAndSourceInfo;
2130 };
2131
2132 //------------------------------------------------------------------------
2134 {
2135 public:
2136 ConditionalBoolTimerScopeId(StringId name, const char* p_source_info, bool b)
2137 {
2138 if (b && FramePro::IsConnected())
2139 {
2140 m_Name = name;
2143 FramePro::StartScope();
2144 }
2145 else
2146 {
2147 m_Name = 0;
2148 mp_SourceInfo = nullptr;
2149 m_StartTime = 0;
2150 }
2151 }
2152
2154 {
2155 if(mp_SourceInfo)
2156 {
2157 int64 end_time = 0;
2159 if(end_time - m_StartTime > FramePro::GetConditionalScopeMinTime())
2160 FramePro::AddTimeSpan(m_Name, mp_SourceInfo, m_StartTime, end_time);
2161 FramePro::StopScope();
2162 }
2163 }
2164
2165 private:
2167 const char* mp_SourceInfo;
2169 };
2170
2171 //------------------------------------------------------------------------
2173 {
2174 public:
2176 {
2177 if (b && FramePro::IsConnected())
2178 {
2181 FramePro::StartScope();
2182 }
2183 else
2184 {
2185 mp_NameAndSourceInfo = nullptr;
2186 m_StartTime = 0;
2187 }
2188 }
2189
2191 {
2193 {
2194 int64 end_time = 0;
2196 if(end_time - m_StartTime > FramePro::GetConditionalScopeMinTime())
2197 FramePro::AddTimeSpan(mp_NameAndSourceInfo, m_StartTime, end_time);
2198 FramePro::StopScope();
2199 }
2200 }
2201
2202 private:
2203 const wchar_t* mp_NameAndSourceInfo;
2205 };
2206
2207 //------------------------------------------------------------------------
2209 {
2210 public:
2212 {
2213 if (FramePro::IsConnected())
2214 {
2215 mp_Name = p_name;
2218 FramePro::StartScope();
2219 }
2220 else
2221 {
2222 mp_Name = nullptr;
2223 mp_SourceInfo = nullptr;
2224 m_StartTime = 0;
2225 }
2226 }
2227
2229 {
2230 if(mp_SourceInfo)
2231 {
2232 int64 end_time = 0;
2234 if(end_time - m_StartTime > FramePro::GetConditionalScopeMinTime())
2235 FramePro::AddTimeSpan(mp_Name, mp_SourceInfo, m_StartTime, end_time);
2236 FramePro::StopScope();
2237 }
2238 }
2239
2240 private:
2241 const char* mp_Name;
2242 const char* mp_SourceInfo;
2244 };
2245
2246 //------------------------------------------------------------------------
2247 class CustomStatTimer
2248 {
2249 public:
2250 CustomStatTimer(const char* p_name)
2251 : m_Value(0),
2252 mp_Next(NULL)
2253 {
2254 mp_Name = p_name;
2255 FramePro::AddCustomStatTimer(this);
2256 }
2257
2258 void Add(uint value)
2259 {
2260 if (mp_Name)
2261 {
2262 uint64 existing_value = m_Value.load(std::memory_order_relaxed);
2264 do
2265 {
2266 uint64 duration = existing_value & 0xffffffffff;
2267 uint64 count = (existing_value >> 40) & 0xffffff;
2268 duration += value;
2269 ++count;
2270 new_value = (count << 40) | duration;
2271
2272 FRAMEPRO_ASSERT(count <= 0xffffff);
2273 FRAMEPRO_ASSERT(duration <= 0xffffffffffL);
2274
2275 } while (!m_Value.compare_exchange_weak(existing_value, new_value, std::memory_order_relaxed, std::memory_order_relaxed));
2276 }
2277 }
2278
2279 void GetAndClear(uint64& value, uint& count)
2280 {
2281 uint64 existing_value = m_Value.load(std::memory_order_relaxed);
2282 while (!m_Value.compare_exchange_weak(existing_value, 0, std::memory_order_relaxed, std::memory_order_relaxed))
2283 ;
2284
2285 value = existing_value & 0xffffffffff;
2286 count = (existing_value >> 40) & 0xffffff;
2287 }
2288
2289 void SetNext(CustomStatTimer* p_next) { mp_Next = p_next; }
2290
2291 CustomStatTimer* GetNext() const { return mp_Next; }
2292
2293 const char* GetName() const { return mp_Name; }
2294
2295 private:
2296 std::atomic<uint64> m_Value;
2297
2299
2300 const char* mp_Name;
2301 };
2302
2303 //------------------------------------------------------------------------
2305 {
2306 public:
2308 {
2309 if (FramePro::IsConnected())
2310 {
2311 mp_Timer = &timer;
2313 }
2314 else
2315 {
2316 mp_Timer = nullptr;
2317 }
2318 }
2319
2321 {
2322 if (mp_Timer)
2323 {
2326
2327 mp_Timer->Add((uint)(end_time - m_StartTime));
2328 }
2329 }
2330
2331 private:
2333 CustomStatTimerScope& operator=(const CustomStatTimerScope&);
2334
2337 };
2338
2339 //------------------------------------------------------------------------
2340 class HiResTimerScope
2341 {
2342 public:
2343 HiResTimerScope(const char* p_name)
2344 {
2345 bool connected = FramePro::IsConnected();
2347
2348 if (connected)
2349 FramePro::StartHiResTimer(p_name);
2350 }
2351
2353 {
2354 if (m_Connected)
2355 FramePro::StopHiResTimer();
2356 }
2357
2358 private:
2359 bool m_Connected;
2360 };
2361
2362 //------------------------------------------------------------------------
2363 class ThreadScope
2364 {
2365 public:
2366 ThreadScope(const char* p_thread_name)
2367 {
2369 }
2370
2371 ~ThreadScope()
2372 {
2373 CleanupThread();
2374 }
2375 };
2376
2377 //------------------------------------------------------------------------
2378 class WaitEventScope
2379 {
2380 public:
2382 {
2383 if (FramePro::IsConnected())
2384 {
2386 m_StartCore = FramePro::GetCore();
2388 }
2389 else
2390 {
2391 m_EventId = 0;
2392 m_StartCore = 0;
2393 m_StartTime = 0;
2394 }
2395 }
2396
2398 {
2399 if (m_EventId)
2400 {
2403
2404 FramePro::AddWaitEvent(m_EventId, m_StartTime, m_StartCore, end_time, FramePro::GetCore());
2405 }
2406 }
2407
2408 private:
2411 int m_StartCore;
2412 };
2413
2414 //------------------------------------------------------------------------
2415 inline unsigned int GetHashAndStackSize(void** p_stack, int& stack_size)
2416 {
2417 #if FRAMEPRO_X64
2418 const unsigned int prime = 0x01000193;
2419 unsigned int hash = prime;
2420 stack_size = 0;
2421 void** p = p_stack;
2422 while(*p)
2423 {
2424 uint64 key = (uint64)(*p++);
2425 key = (~key) + (key << 18);
2426 key = key ^ (key >> 31);
2427 key = key * 21;
2428 key = key ^ (key >> 11);
2429 key = key + (key << 6);
2430 key = key ^ (key >> 22);
2431 hash = hash ^ (unsigned int)key;
2432 ++stack_size;
2433 }
2434
2435 return hash;
2436 #else
2437 const unsigned int prime = 0x01000193;
2438 unsigned int hash = prime;
2439 stack_size = 0;
2440 while(p_stack[stack_size])
2441 {
2442 hash = (hash * prime) ^ (unsigned int)p_stack[stack_size];
2443 ++stack_size;
2444 }
2445
2446 return hash;
2447 #endif
2448 }
2449
2450 //------------------------------------------------------------------------
2451 namespace ThreadState
2452 {
2453 enum Enum
2454 {
2455 Initialized = 0,
2456 Ready,
2457 Running,
2458 Standby,
2459 Terminated,
2460 Waiting,
2461 Transition,
2463
2464 Reserved1,
2465 Reserved2,
2466 Reserved3,
2467 Reserved4,
2468 Reserved5,
2469 Reserved6,
2470 Reserved7,
2471 Reserved8,
2472 Reserved9,
2473 Reserved10,
2474 Reserved11,
2475 Reserved12,
2476 };
2477 }
2478
2479 //------------------------------------------------------------------------
2480 namespace ThreadWaitReason
2481 {
2482 enum Enum
2483 {
2484 Executive = 0,
2485 FreePage,
2486 PageIn,
2489 Suspended,
2492 WrFreePage,
2493 WrPageIn,
2499 WrQueue,
2501 WrLpcReply,
2503 WrPageOut,
2510 WrKernel,
2511 WrResource,
2512 WrPushLock,
2513 WrMutex,
2520 WrRundown,
2522 };
2523 }
2524
2525 //------------------------------------------------------------------------
2526 struct ContextSwitch
2527 {
2529 int m_ProcessId;
2530 int m_CPUId;
2531 int m_OldThreadId;
2532 int m_NewThreadId;
2533 ThreadState::Enum m_OldThreadState;
2534 ThreadWaitReason::Enum m_OldThreadWaitReason;
2535 };
2536}
2537
2538//------------------------------------------------------------------------
2539
2540//------------------------------------------------------------------------
2541//
2542// Array.h
2543//
2544#include <memory.h>
2545
2546//------------------------------------------------------------------------
2547#if FRAMEPRO_ENABLED
2548
2549//------------------------------------------------------------------------
2550namespace FramePro
2551{
2552 //--------------------------------------------------------------------
2553 template<typename T>
2554 class Array
2555 {
2556 public:
2557 //--------------------------------------------------------------------
2558 Array()
2559 : mp_Array(NULL),
2560 m_Count(0),
2561 m_Capacity(0),
2563 {
2564 }
2565
2566 //--------------------------------------------------------------------
2567 ~Array()
2568 {
2570 }
2571
2572 //--------------------------------------------------------------------
2573 int GetCount() const
2574 {
2575 return m_Count;
2576 }
2577
2578 //--------------------------------------------------------------------
2579 void Clear()
2580 {
2581 if(mp_Array)
2582 {
2583 mp_Allocator->Free(mp_Array);
2584 mp_Array = NULL;
2585 }
2586
2587 m_Count = 0;
2588 m_Capacity = 0;
2589 }
2590
2591 //--------------------------------------------------------------------
2592 void ClearNoFree()
2593 {
2594 m_Count = 0;
2595 }
2596
2597 //--------------------------------------------------------------------
2598 void SetAllocator(Allocator* p_allocator)
2599 {
2602 }
2603
2604 //--------------------------------------------------------------------
2605 bool Add(const T& value)
2606 {
2607 if (m_Count == m_Capacity)
2608 {
2609 if (!Grow())
2610 return false;
2611 }
2612
2613 mp_Array[m_Count] = value;
2614 ++m_Count;
2615
2616 return true;
2617 }
2618
2619 //--------------------------------------------------------------------
2620 const T& operator[](int index) const
2621 {
2622 FRAMEPRO_ASSERT(index >= 0 && index < m_Count);
2623 return mp_Array[index];
2624 }
2625
2626 //--------------------------------------------------------------------
2627 T& operator[](int index)
2628 {
2629 FRAMEPRO_ASSERT(index >= 0 && index < m_Count);
2630 return mp_Array[index];
2631 }
2632
2633 //--------------------------------------------------------------------
2634 void RemoveAt(int index)
2635 {
2636 FRAMEPRO_ASSERT(index >= 0 && index < m_Count);
2637
2638 if(index < m_Count - 1)
2639 memmove(mp_Array + index, mp_Array + index + 1, (m_Count - 1 - index) * sizeof(T));
2640
2641 --m_Count;
2642 }
2643
2644 //--------------------------------------------------------------------
2645 T RemoveLast()
2646 {
2648
2649 return mp_Array[--m_Count];
2650 }
2651
2652 //--------------------------------------------------------------------
2653 bool Contains(const T& value) const
2654 {
2655 for(int i=0; i<m_Count; ++i)
2656 if(mp_Array[i] == value)
2657 return true;
2658 return false;
2659 }
2660
2661 //--------------------------------------------------------------------
2662 bool Resize(int count)
2663 {
2664 int new_capacity = m_Count + count;
2665
2667 {
2668 m_Capacity = m_Capacity ? 2 * m_Capacity : 32;
2669 while (m_Capacity < new_capacity)
2670 m_Capacity *= 2;
2671
2672 T* p_new_array = (T*)mp_Allocator->Alloc(sizeof(T)*m_Capacity);
2673 if (!p_new_array)
2674 {
2675 mp_Array = NULL;
2676 return false;
2677 }
2678
2679 if (mp_Array)
2680 memcpy(p_new_array, mp_Array, sizeof(T)*m_Count);
2681 mp_Allocator->Free(mp_Array);
2683 }
2684
2685 m_Count = count;
2686
2687 return true;
2688 }
2689
2690 private:
2691 //--------------------------------------------------------------------
2692 bool Grow()
2693 {
2694 m_Capacity = m_Capacity ? 2*m_Capacity : 32;
2695
2696 T* p_new_array = (T*)mp_Allocator->Alloc(sizeof(T)*m_Capacity);
2697 if (!p_new_array)
2698 {
2699 mp_Array = NULL;
2700 return false;
2701 }
2702
2703 if(mp_Array)
2704 memcpy(p_new_array, mp_Array, sizeof(T)*m_Count);
2705
2706 mp_Allocator->Free(mp_Array);
2708
2709 return true;
2710 }
2711
2712 //------------------------------------------------------------------------
2713 // data
2714 private:
2715 T* mp_Array;
2716
2717 int m_Count;
2718 int m_Capacity;
2719
2721 };
2722}
2723
2724//------------------------------------------------------------------------
2725#endif // #if FRAMEPRO_ENABLED
2726
2727//------------------------------------------------------------------------
2728#endif // #if FRAMEPRO_ENABLED
2729
2730//------------------------------------------------------------------------
2731#endif // #ifndef FRAMEPRO_H_INCLUDED
2732
OODEFFUNC typedef void(OODLE_CALLBACK t_fp_OodleCore_Plugin_Free)(void *ptr)
#define NULL
Definition oodle2base.h:134
@ PS4
Definition AndroidInputInterface.h:118
FPlatformTypes::int64 int64
A 64-bit signed integer.
Definition Platform.h:1127
FPlatformTypes::uint64 uint64
A 64-bit unsigned integer.
Definition Platform.h:1117
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
const bool
Definition NetworkReplayStreaming.h:178
memcpy(InputBufferBase, BinkBlocksData, BinkBlocksSize)
@ Contains
Definition AutomationTest.h:160
Type SetThreadPriority(Type ThreadAndIndex, Type ThreadPriority)
Definition TaskGraphInterfaces.h:190
@ Waiting
Definition PathFollowingComponent.h:42
IMAGECORE_API const TCHAR * GetName(Type Format)
Definition ImageCore.cpp:1378
FString ToString(uint16 Value)
Definition PathFollowingComponent.cpp:82
Definition FramePro.h:208
long long StringId
Definition FramePro.h:209
bool SocketSend(void *p_os_socket_mem, void *p_buffer, int size)
void CreateThread(void *p_os_thread_mem, int os_thread_mem_size)
bool BindSocket(void *p_os_socket_mem, const char *p_port)
void SetEvent(void *p_os_event_mem)
void DestroyEvent(void *p_os_event_mem)
bool OpenFileForWrite(void *p_os_file_mem, const char *p_filename)
void CreateLock(void *p_os_lock_mem, int os_lock_mem_size)
void DestroyLock(void *p_os_lock_mem)
void ResetEvent(void *p_os_event_mem)
void TakeLock(void *p_os_lock_mem)
void GetStackTrace(void **stack, int &stack_size, unsigned int &hash)
void DebugWrite(const char *p_message)
void * Alloc(int size)
bool AcceptSocket(void *p_os_socket_mem, void *p_client_os_socket_mem)
void CreateSocket(void *p_os_socket_mem, int os_socket_mem_size)
void ReleaseLock(void *p_os_lock_mem)
int WaitEvent(void *p_os_event_mem, int timeout)
void CloseFile(void *p_os_file_mem)
void DestroyThread(void *p_os_thread_mem)
int SocketReceive(void *p_os_socket_mem, void *p_buffer, int size)
void SetThreadName(unsigned int thread_id, const char *p_name)
int
Definition TestServer.py:515
uint32 GetNext(uint32 Index, const IndexType *NextIndexData, const uint32 NextIndexCount)
Definition CompactHashTable.h:116
void WriteToFile(const FString &Filename, const uint8 *InDataPtr, int64 InDataSize)
Definition SavePackageUtilities.cpp:534
Definition MinimalWindowsApi.h:62
MINIMAL_WINDOWS_API DWORD WINAPI GetCurrentThreadId()
Definition OpenGLBuffer.cpp:37