diff --git a/Code/Framework/AzCore/AzCore/Debug/ProfilerBus.h b/Code/Framework/AzCore/AzCore/Debug/ProfilerBus.h index 322bfb60c2..8c5c6de902 100644 --- a/Code/Framework/AzCore/AzCore/Debug/ProfilerBus.h +++ b/Code/Framework/AzCore/AzCore/Debug/ProfilerBus.h @@ -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; diff --git a/Gems/Profiler/Code/Source/CpuProfilerImpl.cpp b/Gems/Profiler/Code/Source/CpuProfiler.cpp similarity index 91% rename from Gems/Profiler/Code/Source/CpuProfilerImpl.cpp rename to Gems/Profiler/Code/Source/CpuProfiler.cpp index b0082bd046..7fa1277019 100644 --- a/Gems/Profiler/Code/Source/CpuProfilerImpl.cpp +++ b/Gems/Profiler/Code/Source/CpuProfiler.cpp @@ -6,7 +6,7 @@ * */ -#include +#include #include #include @@ -15,14 +15,7 @@ namespace Profiler { - thread_local CpuTimingLocalStorage* CpuProfilerImpl::ms_threadLocalStorage = nullptr; - - // --- CpuProfiler --- - - CpuProfiler* CpuProfiler::Get() - { - return AZ::Interface::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::Register(this); - AZ::Interface::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::Unregister(this); AZ::Interface::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& flushTarget) + bool CpuProfiler::EndContinuousCapture(AZStd::ring_buffer& 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 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 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& continuousData) + CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializer(const AZStd::ring_buffer& continuousData) { // Create serializable entries for (const auto& timeRegionMap : continuousData) diff --git a/Gems/Profiler/Code/Source/CpuProfiler.h b/Gems/Profiler/Code/Source/CpuProfiler.h index 9235ac7da9..2595516ef6 100644 --- a/Gems/Profiler/Code/Source/CpuProfiler.h +++ b/Gems/Profiler/Code/Source/CpuProfiler.h @@ -8,10 +8,17 @@ #pragma once +#include #include +#include +#include #include +#include #include #include +#include +#include +#include #include 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>; + using TimeRegionMap = AZStd::unordered_map; + + //! 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 { + friend class CpuProfiler; + public: - using ThreadTimeRegionMap = AZStd::unordered_map>; - using TimeRegionMap = AZStd::unordered_map; + 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 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 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 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& 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, 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& 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 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& continuousData); - virtual bool IsProfilerEnabled() const = 0 ; + AZStd::vector m_cpuProfilingStatisticsSerializerEntries; }; } // namespace Profiler diff --git a/Gems/Profiler/Code/Source/CpuProfilerImpl.h b/Gems/Profiler/Code/Source/CpuProfilerImpl.h deleted file mode 100644 index 48b972bc49..0000000000 --- a/Gems/Profiler/Code/Source/CpuProfilerImpl.h +++ /dev/null @@ -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 - -#include -#include -#include -#include -#include -#include -#include -#include - -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 - { - 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 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 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 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& 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, 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 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& continuousData); - - AZStd::vector m_cpuProfilingStatisticsSerializerEntries; - }; -}; // namespace Profiler diff --git a/Gems/Profiler/Code/Source/ImGuiCpuProfiler.cpp b/Gems/Profiler/Code/Source/ImGuiCpuProfiler.cpp index c4da3ab45a..c2cf705015 100644 --- a/Gems/Profiler/Code/Source/ImGuiCpuProfiler.cpp +++ b/Gems/Profiler/Code/Source/ImGuiCpuProfiler.cpp @@ -10,7 +10,7 @@ #include -#include +#include #include #include @@ -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::Get(); + auto cpuProfiler = azrtti_cast(profilerInterface); + + const TimeRegionMap& timeRegionMap = cpuProfiler->GetTimeRegionMap(); AZ::s64 viewportStartTick = AZStd::numeric_limits::max(); AZ::s64 viewportEndTick = AZStd::numeric_limits::lowest(); diff --git a/Gems/Profiler/Code/Source/ProfilerImGuiSystemComponent.cpp b/Gems/Profiler/Code/Source/ProfilerImGuiSystemComponent.cpp index 62d27a1806..0fb37c7634 100644 --- a/Gems/Profiler/Code/Source/ProfilerImGuiSystemComponent.cpp +++ b/Gems/Profiler/Code/Source/ProfilerImGuiSystemComponent.cpp @@ -8,6 +8,7 @@ #include +#include #include #include #include @@ -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(); } diff --git a/Gems/Profiler/Code/Source/ProfilerSystemComponent.cpp b/Gems/Profiler/Code/Source/ProfilerSystemComponent.cpp index 24da9e050e..975109935d 100644 --- a/Gems/Profiler/Code/Source/ProfilerSystemComponent.cpp +++ b/Gems/Profiler/Code/Source/ProfilerSystemComponent.cpp @@ -51,7 +51,7 @@ namespace Profiler int m_framesLeft{ 0 }; }; - bool SerializeCpuProfilingData(const AZStd::ring_buffer& data, AZStd::string outputFilePath, bool wasEnabled) + bool SerializeCpuProfilingData(const AZStd::ring_buffer& 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 singleFrameData(1); + AZStd::ring_buffer 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 captureResult; + AZStd::ring_buffer 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 diff --git a/Gems/Profiler/Code/Source/ProfilerSystemComponent.h b/Gems/Profiler/Code/Source/ProfilerSystemComponent.h index a1c8c47479..b435dec013 100644 --- a/Gems/Profiler/Code/Source/ProfilerSystemComponent.h +++ b/Gems/Profiler/Code/Source/ProfilerSystemComponent.h @@ -8,7 +8,7 @@ #pragma once -#include +#include #include #include @@ -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; }; diff --git a/Gems/Profiler/Code/profiler_files.cmake b/Gems/Profiler/Code/profiler_files.cmake index ebbca1cd78..c5aaac0d24 100644 --- a/Gems/Profiler/Code/profiler_files.cmake +++ b/Gems/Profiler/Code/profiler_files.cmake @@ -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 )