Add Tracy profiler support

This commit is contained in:
Wojtek Figat
2021-05-02 11:24:42 +02:00
parent 1a261597c5
commit 543d1a3c0e
45 changed files with 14752 additions and 108 deletions

View File

@@ -14,7 +14,7 @@
#include "Engine/Core/Math/Rectangle.h"
#include "Engine/Core/Utilities.h"
#if COMPILE_WITH_PROFILER
#include "Engine/Profiler/ProfilerMemory.h"
#include "Engine/Profiler/ProfilerCPU.h"
#endif
#include "Engine/Threading/Threading.h"
#include "Engine/Engine/CommandLine.h"
@@ -165,6 +165,44 @@ void PlatformBase::Exit()
{
}
#if COMPILE_WITH_PROFILER
void PlatformBase::OnMemoryAlloc(void* ptr, uint64 size)
{
if (!ptr)
return;
#if TRACY_ENABLE
// Track memory allocation in Tracy
//tracy::Profiler::MemAlloc(ptr, size, false);
tracy::Profiler::MemAllocCallstack(ptr, size, 12, false);
#endif
// Register allocation during the current CPU event
auto thread = ProfilerCPU::GetCurrentThread();
if (thread != nullptr && thread->Buffer.GetCount() != 0)
{
auto& activeEvent = thread->Buffer.Last().Event();
if (activeEvent.End < ZeroTolerance)
{
activeEvent.NativeMemoryAllocation += (int32)size;
}
}
}
void PlatformBase::OnMemoryFree(void* ptr)
{
if (!ptr)
return;
#if TRACY_ENABLE
// Track memory allocation in Tracy
tracy::Profiler::MemFree(ptr, false);
#endif
}
#endif
void* PlatformBase::AllocatePages(uint64 numPages, uint64 pageSize)
{
// Fallback to the default memory allocation
@@ -460,15 +498,6 @@ Vector2 PlatformBase::GetVirtualDesktopSize()
return Platform::GetVirtualDesktopBounds().Size;
}
#if COMPILE_WITH_PROFILER
void PlatformBase::TrackAllocation(uint64 size)
{
ProfilerMemory::OnAllocation((uint32)size, false);
}
#endif
void PlatformBase::GetEnvironmentVariables(Dictionary<String, String>& result)
{
// Not supported

View File

@@ -299,7 +299,8 @@ public:
static void Prefetch(void const* ptr) = delete;
#if COMPILE_WITH_PROFILER
static void TrackAllocation(uint64 size);
static void OnMemoryAlloc(void* ptr, uint64 size);
static void OnMemoryFree(void* ptr);
#endif
/// <summary>

View File

@@ -4,6 +4,10 @@
#include "Engine/Threading/IRunnable.h"
#include "Engine/Threading/ThreadRegistry.h"
#include "Engine/Core/Log.h"
#if TRACY_ENABLE
#include "Engine/Core/Math/Math.h"
#include <ThirdParty/tracy/Tracy.h>
#endif
Delegate<Thread*> ThreadBase::ThreadStarting;
Delegate<Thread*, int32> ThreadBase::ThreadExiting;
@@ -70,6 +74,13 @@ int32 ThreadBase::Run()
ASSERT(_runnable);
const auto thread = static_cast<Thread*>(this);
_id = Platform::GetCurrentThreadID();
#if TRACY_ENABLE
char threadName[100];
const int32 threadNameLength = Math::Min<int32>(ARRAY_COUNT(threadName) - 1, _name.Length());
StringUtils::ConvertUTF162ANSI(*_name, threadName, threadNameLength);
threadName[threadNameLength] = 0;
tracy::SetThreadName(threadName);
#endif
ThreadRegistry::Add(thread);
ThreadStarting(thread);
int32 exitCode = 1;

View File

@@ -305,14 +305,18 @@ void Win32Platform::Prefetch(void const* ptr)
void* Win32Platform::Allocate(uint64 size, uint64 alignment)
{
void* ptr = _aligned_malloc((size_t)size, (size_t)alignment);
#if COMPILE_WITH_PROFILER
TrackAllocation(size);
OnMemoryAlloc(ptr, size);
#endif
return _aligned_malloc((size_t)size, (size_t)alignment);
return ptr;
}
void Win32Platform::Free(void* ptr)
{
#if COMPILE_WITH_PROFILER
OnMemoryFree(ptr);
#endif
_aligned_free(ptr);
}

View File

@@ -37,9 +37,30 @@ namespace
int32 SystemDpi = 96;
#if CRASH_LOG_ENABLE
CriticalSection SymLocker;
#if TRACY_ENABLE
bool SymInitialized = true;
#else
bool SymInitialized = false;
bool SymModulesDirty = true;
#endif
Array<String> SymbolsPath;
void OnSymbolsPathModified()
{
if (!SymInitialized)
return;
HANDLE process = GetCurrentProcess();
SymCleanup(process);
String symbolSearchPath;
for (auto& path : SymbolsPath)
{
symbolSearchPath += path;
symbolSearchPath += ";";
}
symbolSearchPath += Platform::GetWorkingDirectory();
SymInitializeW(process, *symbolSearchPath, TRUE);
//SymSetSearchPathW(process, *symbolSearchPath);
//SymRefreshModuleList(process);
}
#endif
}
@@ -378,6 +399,20 @@ void WindowsPlatform::PreInit(void* hInstance)
Error(TEXT("OLE initalization failed!"));
exit(-1);
}
#if CRASH_LOG_ENABLE
TCHAR buffer[MAX_PATH] = { 0 };
SymLocker.Lock();
if (::GetModuleFileNameW(::GetModuleHandleW(nullptr), buffer, MAX_PATH))
SymbolsPath.Add(StringUtils::GetDirectoryName(buffer));
if (::GetEnvironmentVariableW(TEXT("_NT_SYMBOL_PATH"), buffer, MAX_PATH))
SymbolsPath.Add(StringUtils::GetDirectoryName(buffer));
DWORD options = SymGetOptions();
options |= SYMOPT_LOAD_LINES | SYMOPT_FAIL_CRITICAL_ERRORS | SYMOPT_DEFERRED_LOADS | SYMOPT_EXACT_SYMBOLS;
SymSetOptions(options);
OnSymbolsPathModified();
SymLocker.Unlock();
#endif
}
bool WindowsPlatform::IsWindows10()
@@ -604,11 +639,13 @@ void WindowsPlatform::Exit()
{
#if CRASH_LOG_ENABLE
SymLocker.Lock();
#if !TRACY_ENABLE
if (SymInitialized)
{
SymInitialized = false;
SymCleanup(GetCurrentProcess());
}
#endif
SymbolsPath.Resize(0);
SymLocker.Unlock();
#endif
@@ -650,25 +687,20 @@ void WindowsPlatform::SetHighDpiAwarenessEnabled(bool enable)
const HMODULE shCoreDll = LoadLibraryW(L"Shcore.dll");
if (!shCoreDll)
return;
typedef enum _PROCESS_DPI_AWARENESS
{
PROCESS_DPI_UNAWARE = 0,
PROCESS_SYSTEM_DPI_AWARE = 1,
PROCESS_PER_MONITOR_DPI_AWARE = 2
} PROCESS_DPI_AWARENESS;
typedef HRESULT (STDAPICALLTYPE *SetProcessDpiAwarenessProc)(PROCESS_DPI_AWARENESS Value);
const SetProcessDpiAwarenessProc setProcessDpiAwareness = (SetProcessDpiAwarenessProc)GetProcAddress(shCoreDll, "SetProcessDpiAwareness");
if (setProcessDpiAwareness)
{
setProcessDpiAwareness(enable ? PROCESS_PER_MONITOR_DPI_AWARE : PROCESS_DPI_UNAWARE);
}
SystemDpi = CalculateDpi(shCoreDll);
FreeLibrary(shCoreDll);
::FreeLibrary(shCoreDll);
}
BatteryInfo WindowsPlatform::GetBatteryInfo()
@@ -1108,10 +1140,9 @@ void* WindowsPlatform::LoadLibrary(const Char* filename)
SymLocker.Lock();
const auto folder = StringUtils::GetDirectoryName(filename);
if (!SymbolsPath.Contains(folder))
SymbolsPath.Add(folder);
if (SymInitialized)
{
SymModulesDirty = true;
SymbolsPath.Add(folder);
OnSymbolsPathModified();
}
SymLocker.Unlock();
#endif
@@ -1131,46 +1162,16 @@ Array<PlatformBase::StackFrame> WindowsPlatform::GetStackFrames(int32 skipCount,
if (!SymInitialized)
{
SymInitialized = true;
// Build search path
String symbolSearchPath;
TCHAR ModulePath[MAX_PATH] = { 0 };
if (::GetModuleFileName(::GetModuleHandle(nullptr), ModulePath, MAX_PATH))
{
symbolSearchPath += StringUtils::GetDirectoryName(ModulePath);
symbolSearchPath += ";";
}
for (auto& path : SymbolsPath)
{
symbolSearchPath += path;
symbolSearchPath += ";";
}
String _NT_SYMBOL_PATH;
if (!Platform::GetEnvironmentVariable(TEXT("_NT_SYMBOL_PATH"), _NT_SYMBOL_PATH))
{
symbolSearchPath += _NT_SYMBOL_PATH;
symbolSearchPath += ";";
}
symbolSearchPath += Platform::GetWorkingDirectory();
symbolSearchPath += ";";
DWORD options = SymGetOptions();
options |= SYMOPT_LOAD_LINES;
options |= SYMOPT_FAIL_CRITICAL_ERRORS;
options |= SYMOPT_DEFERRED_LOADS;
options |= SYMOPT_EXACT_SYMBOLS;
SymSetOptions(options);
SymInitializeW(process, *symbolSearchPath, TRUE);
}
// Refresh modules if needed
if (SymModulesDirty)
{
SymModulesDirty = false;
SymRefreshModuleList(process);
}
// Capture the context if missing
/*EXCEPTION_POINTERS exceptionPointers;
CONTEXT contextData;