[development] Profiler gem cleanup (#7533)

Consolidated the contents of CpuProfilerImp.h into CpuProfiler.h
Renamed CpuProfilerImpl.cpp to CpuProfiler.cpp
Collapsed the CpuProfilerImpl class into the intermediary CpuProfiler interface class, removing that interface type
Replaced all calls to the old CpuProfiler interface with AZ::Debug::ProfilerSystemInterface
Added accessor to see if a continuous capture is in progress to AZ::Debug::ProfilerRequests

Signed-off-by: AMZN-ScottR 24445312+AMZN-ScottR@users.noreply.github.com
monroegm-disable-blank-issue-2
Scott Romero 4 years ago committed by GitHub
parent 2589cb20e5
commit a20f48915e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -58,6 +58,10 @@ namespace AZ
//! Starting/ending a multi-frame capture of profiling data
virtual bool StartCapture(AZStd::string outputFilePath) = 0;
virtual bool EndCapture() = 0;
//! Check to see if a programmatic capture is currently in progress, implies
//! that the profiler is active if returns True.
virtual bool IsCaptureInProgress() const = 0;
};
using ProfilerSystemInterface = AZ::Interface<ProfilerRequests>;

@ -6,7 +6,7 @@
*
*/
#include <CpuProfilerImpl.h>
#include <CpuProfiler.h>
#include <AzCore/Interface/Interface.h>
#include <AzCore/Serialization/SerializeContext.h>
@ -15,14 +15,7 @@
namespace Profiler
{
thread_local CpuTimingLocalStorage* CpuProfilerImpl::ms_threadLocalStorage = nullptr;
// --- CpuProfiler ---
CpuProfiler* CpuProfiler::Get()
{
return AZ::Interface<CpuProfiler>::Get();
}
thread_local CpuTimingLocalStorage* CpuProfiler::ms_threadLocalStorage = nullptr;
// --- CachedTimeRegion ---
@ -61,25 +54,24 @@ namespace Profiler
}
// --- CpuProfilerImpl ---
// --- CpuProfiler ---
void CpuProfilerImpl::Init()
void CpuProfiler::Init()
{
AZ::Interface<AZ::Debug::Profiler>::Register(this);
AZ::Interface<CpuProfiler>::Register(this);
m_initialized = true;
AZ::SystemTickBus::Handler::BusConnect();
m_continuousCaptureData.set_capacity(10);
}
void CpuProfilerImpl::Shutdown()
void CpuProfiler::Shutdown()
{
if (!m_initialized)
{
return;
}
// When this call is made, no more thread profiling calls can be performed anymore
AZ::Interface<CpuProfiler>::Unregister(this);
AZ::Interface<AZ::Debug::Profiler>::Unregister(this);
// Wait for the remaining threads that might still be processing its profiling calls
@ -96,7 +88,7 @@ namespace Profiler
AZ::SystemTickBus::Handler::BusDisconnect();
}
void CpuProfilerImpl::BeginRegion(const AZ::Debug::Budget* budget, const char* eventName, [[maybe_unused]] size_t eventNameArgCount, ...)
void CpuProfiler::BeginRegion(const AZ::Debug::Budget* budget, const char* eventName, [[maybe_unused]] size_t eventNameArgCount, ...)
{
// Try to lock here, the shutdownMutex will only be contested when the CpuProfiler is shutting down.
if (m_shutdownMutex.try_lock_shared())
@ -115,7 +107,7 @@ namespace Profiler
}
}
void CpuProfilerImpl::EndRegion([[maybe_unused]] const AZ::Debug::Budget* budget)
void CpuProfiler::EndRegion([[maybe_unused]] const AZ::Debug::Budget* budget)
{
// Try to lock here, the shutdownMutex will only be contested when the CpuProfiler is shutting down.
if (m_shutdownMutex.try_lock_shared())
@ -130,12 +122,12 @@ namespace Profiler
}
}
const CpuProfiler::TimeRegionMap& CpuProfilerImpl::GetTimeRegionMap() const
const TimeRegionMap& CpuProfiler::GetTimeRegionMap() const
{
return m_timeRegionMap;
}
bool CpuProfilerImpl::BeginContinuousCapture()
bool CpuProfiler::BeginContinuousCapture()
{
bool expected = false;
if (m_continuousCaptureInProgress.compare_exchange_strong(expected, true))
@ -149,7 +141,7 @@ namespace Profiler
return false;
}
bool CpuProfilerImpl::EndContinuousCapture(AZStd::ring_buffer<TimeRegionMap>& flushTarget)
bool CpuProfiler::EndContinuousCapture(AZStd::ring_buffer<TimeRegionMap>& flushTarget)
{
if (!m_continuousCaptureInProgress.load())
{
@ -172,12 +164,12 @@ namespace Profiler
return false;
}
bool CpuProfilerImpl::IsContinuousCaptureInProgress() const
bool CpuProfiler::IsContinuousCaptureInProgress() const
{
return m_continuousCaptureInProgress.load();
}
void CpuProfilerImpl::SetProfilerEnabled(bool enabled)
void CpuProfiler::SetProfilerEnabled(bool enabled)
{
AZStd::unique_lock<AZStd::mutex> lock(m_threadRegisterMutex);
@ -204,12 +196,12 @@ namespace Profiler
}
}
bool CpuProfilerImpl::IsProfilerEnabled() const
bool CpuProfiler::IsProfilerEnabled() const
{
return m_enabled;
}
void CpuProfilerImpl::OnSystemTick()
void CpuProfiler::OnSystemTick()
{
if (!m_enabled)
{
@ -249,7 +241,7 @@ namespace Profiler
m_timeRegionMap = AZStd::move(newMap);
}
void CpuProfilerImpl::RegisterThreadStorage()
void CpuProfiler::RegisterThreadStorage()
{
AZStd::unique_lock<AZStd::mutex> lock(m_threadRegisterMutex);
if (!ms_threadLocalStorage)
@ -371,7 +363,7 @@ namespace Profiler
}
}
void CpuTimingLocalStorage::TryFlushCachedMap(CpuProfiler::ThreadTimeRegionMap& cachedTimeRegionMap)
void CpuTimingLocalStorage::TryFlushCachedMap(ThreadTimeRegionMap& cachedTimeRegionMap)
{
// Try to lock, if it's already in use (the cached regions in the array are being copied to the map)
// it'll show up in the next iteration when the user requests it.
@ -397,7 +389,7 @@ namespace Profiler
// --- CpuProfilingStatisticsSerializer ---
CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializer(const AZStd::ring_buffer<CpuProfiler::TimeRegionMap>& continuousData)
CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializer(const AZStd::ring_buffer<TimeRegionMap>& continuousData)
{
// Create serializable entries
for (const auto& timeRegionMap : continuousData)

@ -8,10 +8,17 @@
#pragma once
#include <AzCore/Component/TickBus.h>
#include <AzCore/Debug/Profiler.h>
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/Name/Name.h>
#include <AzCore/RTTI/RTTI.h>
#include <AzCore/std/containers/map.h>
#include <AzCore/std/containers/ring_buffer.h>
#include <AzCore/std/containers/unordered_map.h>
#include <AzCore/std/parallel/mutex.h>
#include <AzCore/std/parallel/shared_mutex.h>
#include <AzCore/std/smart_ptr/intrusive_refcount.h>
#include <AzCore/std/string/string.h>
namespace Profiler
@ -47,36 +54,178 @@ namespace Profiler
AZStd::sys_time_t m_endTick = 0;
};
//! Interface class of the CpuProfiler
class CpuProfiler
using ThreadTimeRegionMap = AZStd::unordered_map<AZStd::string, AZStd::vector<CachedTimeRegion>>;
using TimeRegionMap = AZStd::unordered_map<AZStd::thread_id, ThreadTimeRegionMap>;
//! Thread local class to keep track of the thread's cached time regions.
//! Each thread keeps track of its own time regions, which is communicated from the CpuProfiler.
//! The CpuProfiler is able to request the cached time regions from the CpuTimingLocalStorage.
class CpuTimingLocalStorage
: public AZStd::intrusive_refcount<AZStd::atomic_uint>
{
friend class CpuProfiler;
public:
using ThreadTimeRegionMap = AZStd::unordered_map<AZStd::string, AZStd::vector<CachedTimeRegion>>;
using TimeRegionMap = AZStd::unordered_map<AZStd::thread_id, ThreadTimeRegionMap>;
AZ_CLASS_ALLOCATOR(CpuTimingLocalStorage, AZ::SystemAllocator, 0);
CpuTimingLocalStorage();
~CpuTimingLocalStorage();
private:
// Maximum stack size
static constexpr uint32_t TimeRegionStackSize = 2048u;
// Adds a region to the stack, gets called each time a region begins
void RegionStackPushBack(CachedTimeRegion& timeRegion);
// Pops a region from the stack, gets called each time a region ends
void RegionStackPopBack();
// Add a new cached time region. If the stack is empty, flush all entries to the cached map
void AddCachedRegion(const CachedTimeRegion& timeRegionCached);
// Tries to flush the map to the passed parameter, only if the thread's mutex is unlocked
void TryFlushCachedMap(ThreadTimeRegionMap& cachedRegionMap);
// Clears m_cachedTimeRegions and resets m_cachedDataLimitReached flag.
void ResetCachedData();
AZStd::thread_id m_executingThreadId;
// Keeps track of the current thread's stack depth
uint32_t m_stackLevel = 0u;
// Cached region map, will be flushed to the system's map when the system requests it
ThreadTimeRegionMap m_cachedTimeRegionMap;
// Use fixed vectors to avoid re-allocating new elements
// Keeps track of the regions that added and removed using the macro
AZStd::fixed_vector<CachedTimeRegion, TimeRegionStackSize> m_timeRegionStack;
// Keeps track of regions that completed (i.e regions that was pushed and popped from the stack)
// Intermediate storage point for the CachedTimeRegions, when the stack is empty, all entries will be
// copied to the map.
AZStd::fixed_vector<CachedTimeRegion, TimeRegionStackSize> m_cachedTimeRegions;
AZStd::mutex m_cachedTimeRegionMutex;
// Dirty flag which is set when the CpuProfiler's enabled state is set from false to true
AZStd::atomic_bool m_clearContainers = false;
// When the thread is terminated, it will flag itself for deletion
AZStd::atomic_bool m_deleteFlag = false;
// Keep track of the regions that have hit the size limit so we don't have to lock to check
AZStd::map<AZStd::string, bool> m_hitSizeLimitMap;
// Keeps track of the first time cached data limit was reached.
bool m_cachedDataLimitReached = false;
};
//! CpuProfiler will keep track of the registered threads, and
//! forwards the request to profile a region to the appropriate thread. The user is able to request all
//! cached regions, which are stored on a per thread frequency.
class CpuProfiler final
: public AZ::Debug::Profiler
, public AZ::SystemTickBus::Handler
{
friend class CpuTimingLocalStorage;
AZ_RTTI(CpuProfiler, "{127C1D0B-BE05-4E18-A8F6-24F3EED2ECA6}");
public:
AZ_RTTI(CpuProfiler, "{10E9D394-FC83-4B45-B2B8-807C6BF07BF0}", AZ::Debug::Profiler);
AZ_CLASS_ALLOCATOR(CpuProfiler, AZ::SystemAllocator, 0);
CpuProfiler() = default;
virtual ~CpuProfiler() = default;
~CpuProfiler() = default;
AZ_DISABLE_COPY_MOVE(CpuProfiler);
//! Registers/un-registers the AZ::Debug::Profiler instance to the interface
void Init();
void Shutdown();
static CpuProfiler* Get();
//! AZ::Debug::Profiler overrides...
void BeginRegion(const AZ::Debug::Budget* budget, const char* eventName, size_t eventNameArgCount, ...) final override;
void EndRegion(const AZ::Debug::Budget* budget) final override;
//! Get the last frame's TimeRegionMap
virtual const TimeRegionMap& GetTimeRegionMap() const = 0;
const TimeRegionMap& GetTimeRegionMap() const;
//! Starting/ending a multi-frame capture of profiling data
bool BeginContinuousCapture();
bool EndContinuousCapture(AZStd::ring_buffer<TimeRegionMap>& flushTarget);
//! Check to see if a programmatic capture is currently in progress, implies
//! that the profiler is active if returns True.
bool IsContinuousCaptureInProgress() const;
//! Getter/setter for the profiler active state
void SetProfilerEnabled(bool enabled);
bool IsProfilerEnabled() const;
//! AZ::SystemTickBus::Handler overrides
//! When fired, the profiler collects all profiling data from registered threads and updates
//! m_timeRegionMap so that the next frame has up-to-date profiling data.
void OnSystemTick() final override;
private:
static constexpr AZStd::size_t MaxFramesToSave = 2 * 60 * 120; // 2 minutes of 120fps
static constexpr AZStd::size_t MaxRegionStringPoolSize = 16384; // Max amount of unique strings to save in the pool before throwing warnings.
// Lazily create and register the local thread data
void RegisterThreadStorage();
// ThreadId -> ThreadTimeRegionMap
// On the start of each frame, this map will be updated with the last frame's profiling data.
TimeRegionMap m_timeRegionMap;
// Set of registered threads when created
AZStd::vector<AZStd::intrusive_ptr<CpuTimingLocalStorage>, AZ::OSStdAllocator> m_registeredThreads;
AZStd::mutex m_threadRegisterMutex;
// Thread local storage, gets lazily allocated when a thread is created
static thread_local CpuTimingLocalStorage* ms_threadLocalStorage;
//! Begin a continuous capture. Blocks the profiler from being toggled off until EndContinuousCapture is called.
[[nodiscard]] virtual bool BeginContinuousCapture() = 0;
// Enable/Disables the threads from profiling
AZStd::atomic_bool m_enabled = false;
//! Flush the CPU Profiler's saved data into the passed ring buffer .
[[nodiscard]] virtual bool EndContinuousCapture(AZStd::ring_buffer<TimeRegionMap>& flushTarget) = 0;
// This lock will only be contested when the CpuProfiler's Shutdown() method has been called
AZStd::shared_mutex m_shutdownMutex;
bool m_initialized = false;
AZStd::mutex m_continuousCaptureEndingMutex;
AZStd::atomic_bool m_continuousCaptureInProgress = false;
// Stores multiple frames of profiling data, size is controlled by MaxFramesToSave. Flushed when EndContinuousCapture is called.
// Ring buffer so that we can have fast append of new data + removal of old profiling data with good cache locality.
AZStd::ring_buffer<TimeRegionMap> m_continuousCaptureData;
};
// Intermediate class to serialize Cpu TimedRegion data.
class CpuProfilingStatisticsSerializer
{
public:
class CpuProfilingStatisticsSerializerEntry
{
public:
AZ_TYPE_INFO(CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializerEntry, "{26B78F65-EB96-46E2-BE7E-A1233880B225}");
static void Reflect(AZ::ReflectContext* context);
CpuProfilingStatisticsSerializerEntry() = default;
CpuProfilingStatisticsSerializerEntry(const CachedTimeRegion& cachedTimeRegion, AZStd::thread_id threadId);
AZ::Name m_groupName;
AZ::Name m_regionName;
uint16_t m_stackDepth;
AZStd::sys_time_t m_startTick;
AZStd::sys_time_t m_endTick;
size_t m_threadId;
};
virtual bool IsContinuousCaptureInProgress() const = 0;
AZ_TYPE_INFO(CpuProfilingStatisticsSerializer, "{D5B02946-0D27-474F-9A44-364C2706DD41}");
static void Reflect(AZ::ReflectContext* context);
//! Enable/Disable the CpuProfiler
virtual void SetProfilerEnabled(bool enabled) = 0;
CpuProfilingStatisticsSerializer() = default;
CpuProfilingStatisticsSerializer(const AZStd::ring_buffer<TimeRegionMap>& continuousData);
virtual bool IsProfilerEnabled() const = 0 ;
AZStd::vector<CpuProfilingStatisticsSerializerEntry> m_cpuProfilingStatisticsSerializerEntries;
};
} // namespace Profiler

@ -1,189 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <CpuProfiler.h>
#include <AzCore/Component/TickBus.h>
#include <AzCore/Memory/OSAllocator.h>
#include <AzCore/Name/Name.h>
#include <AzCore/std/containers/map.h>
#include <AzCore/std/containers/unordered_set.h>
#include <AzCore/std/parallel/mutex.h>
#include <AzCore/std/parallel/shared_mutex.h>
#include <AzCore/std/smart_ptr/intrusive_refcount.h>
namespace Profiler
{
//! Thread local class to keep track of the thread's cached time regions.
//! Each thread keeps track of its own time regions, which is communicated from the CpuProfilerImpl.
//! The CpuProfilerImpl is able to request the cached time regions from the CpuTimingLocalStorage.
class CpuTimingLocalStorage
: public AZStd::intrusive_refcount<AZStd::atomic_uint>
{
friend class CpuProfilerImpl;
public:
AZ_CLASS_ALLOCATOR(CpuTimingLocalStorage, AZ::OSAllocator, 0);
CpuTimingLocalStorage();
~CpuTimingLocalStorage();
private:
// Maximum stack size
static constexpr uint32_t TimeRegionStackSize = 2048u;
// Adds a region to the stack, gets called each time a region begins
void RegionStackPushBack(CachedTimeRegion& timeRegion);
// Pops a region from the stack, gets called each time a region ends
void RegionStackPopBack();
// Add a new cached time region. If the stack is empty, flush all entries to the cached map
void AddCachedRegion(const CachedTimeRegion& timeRegionCached);
// Tries to flush the map to the passed parameter, only if the thread's mutex is unlocked
void TryFlushCachedMap(CpuProfiler::ThreadTimeRegionMap& cachedRegionMap);
// Clears m_cachedTimeRegions and resets m_cachedDataLimitReached flag.
void ResetCachedData();
AZStd::thread_id m_executingThreadId;
// Keeps track of the current thread's stack depth
uint32_t m_stackLevel = 0u;
// Cached region map, will be flushed to the system's map when the system requests it
CpuProfiler::ThreadTimeRegionMap m_cachedTimeRegionMap;
// Use fixed vectors to avoid re-allocating new elements
// Keeps track of the regions that added and removed using the macro
AZStd::fixed_vector<CachedTimeRegion, TimeRegionStackSize> m_timeRegionStack;
// Keeps track of regions that completed (i.e regions that was pushed and popped from the stack)
// Intermediate storage point for the CachedTimeRegions, when the stack is empty, all entries will be
// copied to the map.
AZStd::fixed_vector<CachedTimeRegion, TimeRegionStackSize> m_cachedTimeRegions;
AZStd::mutex m_cachedTimeRegionMutex;
// Dirty flag which is set when the CpuProfiler's enabled state is set from false to true
AZStd::atomic_bool m_clearContainers = false;
// When the thread is terminated, it will flag itself for deletion
AZStd::atomic_bool m_deleteFlag = false;
// Keep track of the regions that have hit the size limit so we don't have to lock to check
AZStd::map<AZStd::string, bool> m_hitSizeLimitMap;
// Keeps track of the first time cached data limit was reached.
bool m_cachedDataLimitReached = false;
};
//! CpuProfiler will keep track of the registered threads, and
//! forwards the request to profile a region to the appropriate thread. The user is able to request all
//! cached regions, which are stored on a per thread frequency.
class CpuProfilerImpl final
: public AZ::Debug::Profiler
, public CpuProfiler
, public AZ::SystemTickBus::Handler
{
friend class CpuTimingLocalStorage;
public:
AZ_TYPE_INFO(CpuProfilerImpl, "{10E9D394-FC83-4B45-B2B8-807C6BF07BF0}");
AZ_CLASS_ALLOCATOR(CpuProfilerImpl, AZ::OSAllocator, 0);
CpuProfilerImpl() = default;
~CpuProfilerImpl() = default;
//! Registers the CpuProfilerImpl instance to the interface
void Init();
//! Unregisters the CpuProfilerImpl instance from the interface
void Shutdown();
// AZ::SystemTickBus::Handler overrides
// When fired, the profiler collects all profiling data from registered threads and updates
// m_timeRegionMap so that the next frame has up-to-date profiling data.
void OnSystemTick() final override;
//! AZ::Debug::Profiler overrides...
void BeginRegion(const AZ::Debug::Budget* budget, const char* eventName, size_t eventNameArgCount, ...) final override;
void EndRegion(const AZ::Debug::Budget* budget) final override;
//! CpuProfiler overrides...
const TimeRegionMap& GetTimeRegionMap() const final override;
bool BeginContinuousCapture() final override;
bool EndContinuousCapture(AZStd::ring_buffer<TimeRegionMap>& flushTarget) final override;
bool IsContinuousCaptureInProgress() const final override;
void SetProfilerEnabled(bool enabled) final override;
bool IsProfilerEnabled() const final override;
private:
static constexpr AZStd::size_t MaxFramesToSave = 2 * 60 * 120; // 2 minutes of 120fps
static constexpr AZStd::size_t MaxRegionStringPoolSize = 16384; // Max amount of unique strings to save in the pool before throwing warnings.
// Lazily create and register the local thread data
void RegisterThreadStorage();
// ThreadId -> ThreadTimeRegionMap
// On the start of each frame, this map will be updated with the last frame's profiling data.
TimeRegionMap m_timeRegionMap;
// Set of registered threads when created
AZStd::vector<AZStd::intrusive_ptr<CpuTimingLocalStorage>, AZ::OSStdAllocator> m_registeredThreads;
AZStd::mutex m_threadRegisterMutex;
// Thread local storage, gets lazily allocated when a thread is created
static thread_local CpuTimingLocalStorage* ms_threadLocalStorage;
// Enable/Disables the threads from profiling
AZStd::atomic_bool m_enabled = false;
// This lock will only be contested when the CpuProfiler's Shutdown() method has been called
AZStd::shared_mutex m_shutdownMutex;
bool m_initialized = false;
AZStd::mutex m_continuousCaptureEndingMutex;
AZStd::atomic_bool m_continuousCaptureInProgress = false;
// Stores multiple frames of profiling data, size is controlled by MaxFramesToSave. Flushed when EndContinuousCapture is called.
// Ring buffer so that we can have fast append of new data + removal of old profiling data with good cache locality.
AZStd::ring_buffer<TimeRegionMap> m_continuousCaptureData;
};
// Intermediate class to serialize Cpu TimedRegion data.
class CpuProfilingStatisticsSerializer
{
public:
class CpuProfilingStatisticsSerializerEntry
{
public:
AZ_TYPE_INFO(CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializerEntry, "{26B78F65-EB96-46E2-BE7E-A1233880B225}");
static void Reflect(AZ::ReflectContext* context);
CpuProfilingStatisticsSerializerEntry() = default;
CpuProfilingStatisticsSerializerEntry(const CachedTimeRegion& cachedTimeRegion, AZStd::thread_id threadId);
AZ::Name m_groupName;
AZ::Name m_regionName;
uint16_t m_stackDepth;
AZStd::sys_time_t m_startTick;
AZStd::sys_time_t m_endTick;
size_t m_threadId;
};
AZ_TYPE_INFO(CpuProfilingStatisticsSerializer, "{D5B02946-0D27-474F-9A44-364C2706DD41}");
static void Reflect(AZ::ReflectContext* context);
CpuProfilingStatisticsSerializer() = default;
CpuProfilingStatisticsSerializer(const AZStd::ring_buffer<CpuProfiler::TimeRegionMap>& continuousData);
AZStd::vector<CpuProfilingStatisticsSerializerEntry> m_cpuProfilingStatisticsSerializerEntries;
};
}; // namespace Profiler

@ -10,7 +10,7 @@
#include <ImGuiCpuProfiler.h>
#include <CpuProfilerImpl.h>
#include <CpuProfiler.h>
#include <AzCore/Debug/ProfilerBus.h>
#include <AzCore/IO/FileIO.h>
@ -176,7 +176,7 @@ namespace Profiler
// Toggle if the bool isn't the same as the cached value
if (cachedShowCpuProfiler != keepDrawing)
{
CpuProfiler::Get()->SetProfilerEnabled(keepDrawing);
AZ::Debug::ProfilerSystemInterface::Get()->SetActive(keepDrawing);
}
}
@ -193,11 +193,11 @@ namespace Profiler
}
ImGui::SameLine();
m_paused = !CpuProfiler::Get()->IsProfilerEnabled();
m_paused = !AZ::Debug::ProfilerSystemInterface::Get()->IsActive();
if (ImGui::Button(m_paused ? "Resume" : "Pause"))
{
m_paused = !m_paused;
CpuProfiler::Get()->SetProfilerEnabled(!m_paused);
AZ::Debug::ProfilerSystemInterface::Get()->SetActive(!m_paused);
}
ImGui::SameLine();
@ -207,7 +207,7 @@ namespace Profiler
}
ImGui::SameLine();
bool isInProgress = CpuProfiler::Get()->IsContinuousCaptureInProgress();
bool isInProgress = AZ::Debug::ProfilerSystemInterface::Get()->IsCaptureInProgress();
if (ImGui::Button(isInProgress ? "End" : "Begin"))
{
auto profilerSystem = AZ::Debug::ProfilerSystemInterface::Get();
@ -445,7 +445,7 @@ namespace Profiler
m_savedData.clear();
m_paused = true;
CpuProfiler::Get()->SetProfilerEnabled(false);
AZ::Debug::ProfilerSystemInterface::Get()->SetActive(false);
m_frameEndTicks.clear();
m_tableData.clear();
@ -708,7 +708,10 @@ namespace Profiler
// compared to if we needed to transform the visualizer's data into the statistical format every frame.
// Get the latest TimeRegionMap
const CpuProfiler::TimeRegionMap& timeRegionMap = CpuProfiler::Get()->GetTimeRegionMap();
auto profilerInterface = AZ::Interface<AZ::Debug::Profiler>::Get();
auto cpuProfiler = azrtti_cast<CpuProfiler*>(profilerInterface);
const TimeRegionMap& timeRegionMap = cpuProfiler->GetTimeRegionMap();
AZ::s64 viewportStartTick = AZStd::numeric_limits<AZ::s64>::max();
AZ::s64 viewportEndTick = AZStd::numeric_limits<AZ::s64>::lowest();

@ -8,6 +8,7 @@
#include <ProfilerImGuiSystemComponent.h>
#include <AzCore/Debug/ProfilerBus.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/EditContextConstants.inl>
@ -107,7 +108,7 @@ namespace Profiler
{
if (ImGui::MenuItem("CPU", "", &m_showCpuProfiler))
{
CpuProfiler::Get()->SetProfilerEnabled(m_showCpuProfiler);
AZ::Debug::ProfilerSystemInterface::Get()->SetActive(m_showCpuProfiler);
}
ImGui::EndMenu();
}

@ -51,7 +51,7 @@ namespace Profiler
int m_framesLeft{ 0 };
};
bool SerializeCpuProfilingData(const AZStd::ring_buffer<CpuProfiler::TimeRegionMap>& data, AZStd::string outputFilePath, bool wasEnabled)
bool SerializeCpuProfilingData(const AZStd::ring_buffer<TimeRegionMap>& data, AZStd::string outputFilePath, bool wasEnabled)
{
AZ_TracePrintf("ProfilerSystemComponent", "Beginning serialization of %zu frames of profiling data\n", data.size());
AZ::JsonSerializerSettings serializationSettings;
@ -78,7 +78,7 @@ namespace Profiler
// Disable the profiler again
if (!wasEnabled)
{
CpuProfiler::Get()->SetProfilerEnabled(false);
AZ::Debug::ProfilerSystemInterface::Get()->SetActive(false);
}
// Notify listeners that the profiler capture has finished.
@ -188,7 +188,7 @@ namespace Profiler
[this, outputFilePath, wasEnabled]()
{
// Blocking call for a single frame of data, avoid thread overhead
AZStd::ring_buffer<CpuProfiler::TimeRegionMap> singleFrameData(1);
AZStd::ring_buffer<TimeRegionMap> singleFrameData(1);
singleFrameData.push_back(m_cpuProfiler.GetTimeRegionMap());
SerializeCpuProfilingData(singleFrameData, outputFilePath, wasEnabled);
m_cpuCaptureInProgress.store(false);
@ -216,7 +216,7 @@ namespace Profiler
return false;
}
AZStd::ring_buffer<CpuProfiler::TimeRegionMap> captureResult;
AZStd::ring_buffer<TimeRegionMap> captureResult;
const bool captureEnded = m_cpuProfiler.EndContinuousCapture(captureResult);
if (!captureEnded)
{
@ -245,4 +245,9 @@ namespace Profiler
return true;
}
bool ProfilerSystemComponent::IsCaptureInProgress() const
{
return m_cpuProfiler.IsContinuousCaptureInProgress();
}
} // namespace Profiler

@ -8,7 +8,7 @@
#pragma once
#include <CpuProfilerImpl.h>
#include <CpuProfiler.h>
#include <AzCore/Component/Component.h>
#include <AzCore/Debug/ProfilerBus.h>
@ -44,6 +44,7 @@ namespace Profiler
bool CaptureFrame(const AZStd::string& outputFilePath) override;
bool StartCapture(AZStd::string outputFilePath) override;
bool EndCapture() override;
bool IsCaptureInProgress() const override;
AZStd::thread m_cpuDataSerializationThread;
@ -51,7 +52,7 @@ namespace Profiler
AZStd::atomic_bool m_cpuCaptureInProgress{ false };
CpuProfilerImpl m_cpuProfiler;
CpuProfiler m_cpuProfiler;
AZStd::string m_captureFile;
};

@ -9,8 +9,7 @@
set(FILES
Include/Profiler/ProfilerImGuiBus.h
Source/CpuProfiler.h
Source/CpuProfilerImpl.cpp
Source/CpuProfilerImpl.h
Source/CpuProfiler.cpp
Source/ProfilerSystemComponent.cpp
Source/ProfilerSystemComponent.h
)

Loading…
Cancel
Save