diff --git a/Gems/Profiler/Code/CMakeLists.txt b/Gems/Profiler/Code/CMakeLists.txt index 15b5fca358..93428e7571 100644 --- a/Gems/Profiler/Code/CMakeLists.txt +++ b/Gems/Profiler/Code/CMakeLists.txt @@ -21,7 +21,6 @@ ly_add_target( PUBLIC AZ::AzCore AZ::AzFramework - Gem::ImGui.Static ) # Here add Profiler target, it depends on the Profiler.Static @@ -38,6 +37,22 @@ ly_add_target( BUILD_DEPENDENCIES PRIVATE Gem::Profiler.Static +) + +ly_add_target( + NAME ProfilerImGui ${PAL_TRAIT_MONOLITHIC_DRIVEN_MODULE_TYPE} + NAMESPACE Gem + FILES_CMAKE + profiler_imgui_shared_files.cmake + INCLUDE_DIRECTORIES + PUBLIC + Include + PRIVATE + Source + BUILD_DEPENDENCIES + PRIVATE + Gem::Profiler.Static + Gem::ImGui.Static RUNTIME_DEPENDENCIES Gem::ImGui ) @@ -45,5 +60,5 @@ ly_add_target( # By default, we will specify that the above target Profiler would be used by # Client and Server type targets when this gem is enabled. If you don't want it # active in Clients or Servers by default, delete one of both of the following lines: -ly_create_alias(NAME Profiler.Clients NAMESPACE Gem TARGETS Gem::Profiler) +ly_create_alias(NAME Profiler.Clients NAMESPACE Gem TARGETS Gem::ProfilerImGui) ly_create_alias(NAME Profiler.Servers NAMESPACE Gem TARGETS Gem::Profiler) diff --git a/Gems/Profiler/Code/Source/ProfilerModuleInterface.h b/Gems/Profiler/Code/Source/ProfilerImGuiModule.cpp similarity index 72% rename from Gems/Profiler/Code/Source/ProfilerModuleInterface.h rename to Gems/Profiler/Code/Source/ProfilerImGuiModule.cpp index 6cf6fd30ab..38cfee2c26 100644 --- a/Gems/Profiler/Code/Source/ProfilerModuleInterface.h +++ b/Gems/Profiler/Code/Source/ProfilerImGuiModule.cpp @@ -6,20 +6,22 @@ * */ +#include +#include + #include #include -#include namespace Profiler { - class ProfilerModuleInterface + class ProfilerImGuiModule : public AZ::Module { public: - AZ_RTTI(ProfilerModuleInterface, "{c966e43a-420d-41c9-bd0d-4cb0bca0d3e1}", AZ::Module); - AZ_CLASS_ALLOCATOR(ProfilerModuleInterface, AZ::SystemAllocator, 0); + AZ_RTTI(ProfilerImGuiModule, "{5946991E-A96C-4E7A-A9B3-605E3C8EC3CB}", AZ::Module); + AZ_CLASS_ALLOCATOR(ProfilerImGuiModule, AZ::SystemAllocator, 0); - ProfilerModuleInterface() + ProfilerImGuiModule() { // Push results of [MyComponent]::CreateDescriptor() into m_descriptors here. // Add ALL components descriptors associated with this gem to m_descriptors. @@ -27,7 +29,8 @@ namespace Profiler // This happens through the [MyComponent]::Reflect() function. m_descriptors.insert(m_descriptors.end(), { ProfilerSystemComponent::CreateDescriptor(), - }); + ProfilerImGuiSystemComponent::CreateDescriptor(), + }); } /** @@ -37,7 +40,10 @@ namespace Profiler { return AZ::ComponentTypeList{ azrtti_typeid(), + azrtti_typeid(), }; } }; }// namespace Profiler + +AZ_DECLARE_MODULE_CLASS(Gem_Profiler, Profiler::ProfilerImGuiModule) diff --git a/Gems/Profiler/Code/Source/ProfilerImGuiSystemComponent.cpp b/Gems/Profiler/Code/Source/ProfilerImGuiSystemComponent.cpp new file mode 100644 index 0000000000..a6dad90d9f --- /dev/null +++ b/Gems/Profiler/Code/Source/ProfilerImGuiSystemComponent.cpp @@ -0,0 +1,103 @@ +/* + * 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 + * + */ + +#include + +#include +#include +#include + +#include + +namespace Profiler +{ + static constexpr AZ::Crc32 profilerImGuiServiceCrc = AZ_CRC_CE("ProfilerImGuiService"); + + void ProfilerImGuiSystemComponent::Reflect(AZ::ReflectContext* context) + { + if (AZ::SerializeContext* serialize = azrtti_cast(context)) + { + serialize->Class() + ->Version(0); + + if (AZ::EditContext* ec = serialize->GetEditContext()) + { + ec->Class("ProfilerImGui", "Provides in-game visualization of the performance data gathered by the ProfilerSystemComponent") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System")) + ->Attribute(AZ::Edit::Attributes::AutoExpand, true); + } + } + } + + void ProfilerImGuiSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + provided.push_back(profilerImGuiServiceCrc); + } + + void ProfilerImGuiSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) + { + incompatible.push_back(profilerImGuiServiceCrc); + } + + void ProfilerImGuiSystemComponent::GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required) + { + } + + void ProfilerImGuiSystemComponent::GetDependentServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& dependent) + { + } + + ProfilerImGuiSystemComponent::ProfilerImGuiSystemComponent() + { + } + + ProfilerImGuiSystemComponent::~ProfilerImGuiSystemComponent() + { + } + + void ProfilerImGuiSystemComponent::Init() + { + } + + void ProfilerImGuiSystemComponent::Activate() + { +#if defined(IMGUI_ENABLED) + ImGui::ImGuiUpdateListenerBus::Handler::BusConnect(); +#endif // defined(IMGUI_ENABLED) + } + + void ProfilerImGuiSystemComponent::Deactivate() + { +#if defined(IMGUI_ENABLED) + ImGui::ImGuiUpdateListenerBus::Handler::BusDisconnect(); +#endif // defined(IMGUI_ENABLED) + } + +#if defined(IMGUI_ENABLED) + void ProfilerImGuiSystemComponent::OnImGuiUpdate() + { + if (m_showCpuProfiler) + { + m_imguiCpuProfiler.Draw(m_showCpuProfiler); + } + } + + void ProfilerImGuiSystemComponent::OnImGuiMainMenuUpdate() + { + if (ImGui::BeginMenu("Profiler")) + { + if (ImGui::MenuItem("CPU", "", &m_showCpuProfiler)) + { + CpuProfiler::Get()->SetProfilerEnabled(m_showCpuProfiler); + } + ImGui::EndMenu(); + } + } +#endif // defined(IMGUI_ENABLED) +} // namespace Profiler diff --git a/Gems/Profiler/Code/Source/ProfilerImGuiSystemComponent.h b/Gems/Profiler/Code/Source/ProfilerImGuiSystemComponent.h new file mode 100644 index 0000000000..8f25e4652a --- /dev/null +++ b/Gems/Profiler/Code/Source/ProfilerImGuiSystemComponent.h @@ -0,0 +1,62 @@ +/* + * 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 + +#if defined(IMGUI_ENABLED) +#include +#include +#endif // defined(IMGUI_ENABLED) + +namespace Profiler +{ + class ProfilerImGuiSystemComponent + : public AZ::Component +#if defined(IMGUI_ENABLED) + , public ImGui::ImGuiUpdateListenerBus::Handler +#endif // defined(IMGUI_ENABLED) + { + public: + AZ_COMPONENT(ProfilerImGuiSystemComponent, "{E59A8A53-6784-4CCB-A8B5-9F91DA9BF1C5}"); + + static void Reflect(AZ::ReflectContext* context); + + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); + static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); + static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required); + static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent); + + ProfilerImGuiSystemComponent(); + ~ProfilerImGuiSystemComponent(); + + protected: + // AZ::Component interface implementation + void Init() override; + void Activate() override; + void Deactivate() override; + +#if defined(IMGUI_ENABLED) + // ImGuiUpdateListenerBus overrides + void OnImGuiUpdate() override; + void OnImGuiMainMenuUpdate() override; +#endif // defined(IMGUI_ENABLED) + + private: +#if defined(IMGUI_ENABLED) + ImGuiCpuProfiler m_imguiCpuProfiler; + bool m_showCpuProfiler{ false }; +#endif // defined(IMGUI_ENABLED) + }; + +} // namespace Profiler diff --git a/Gems/Profiler/Code/Source/ProfilerModule.cpp b/Gems/Profiler/Code/Source/ProfilerModule.cpp index 732265cdb4..055c4cca4d 100644 --- a/Gems/Profiler/Code/Source/ProfilerModule.cpp +++ b/Gems/Profiler/Code/Source/ProfilerModule.cpp @@ -6,17 +6,40 @@ * */ -#include #include +#include +#include + namespace Profiler { class ProfilerModule - : public ProfilerModuleInterface + : public AZ::Module { public: - AZ_RTTI(ProfilerModule, "{1908f95f-30b9-4e27-8ae7-1e9fe487ef87}", ProfilerModuleInterface); + AZ_RTTI(ProfilerModule, "{4A286414-B387-4D20-9A7E-2F792755B769}", AZ::Module); AZ_CLASS_ALLOCATOR(ProfilerModule, AZ::SystemAllocator, 0); + + ProfilerModule() + { + // Push results of [MyComponent]::CreateDescriptor() into m_descriptors here. + // Add ALL components descriptors associated with this gem to m_descriptors. + // This will associate the AzTypeInfo information for the components with the the SerializeContext, BehaviorContext and EditContext. + // This happens through the [MyComponent]::Reflect() function. + m_descriptors.insert(m_descriptors.end(), { + ProfilerSystemComponent::CreateDescriptor(), + }); + } + + /** + * Add required SystemComponents to the SystemEntity. + */ + AZ::ComponentTypeList GetRequiredSystemComponents() const override + { + return AZ::ComponentTypeList{ + azrtti_typeid(), + }; + } }; }// namespace Profiler diff --git a/Gems/Profiler/Code/Source/ProfilerSystemComponent.cpp b/Gems/Profiler/Code/Source/ProfilerSystemComponent.cpp index d6f9adce17..6d4e757b67 100644 --- a/Gems/Profiler/Code/Source/ProfilerSystemComponent.cpp +++ b/Gems/Profiler/Code/Source/ProfilerSystemComponent.cpp @@ -14,33 +14,35 @@ namespace Profiler { + static constexpr AZ::Crc32 profilerServiceCrc = AZ_CRC_CE("ProfilerService"); + void ProfilerSystemComponent::Reflect(AZ::ReflectContext* context) { if (AZ::SerializeContext* serialize = azrtti_cast(context)) { serialize->Class() - ->Version(0) - ; + ->Version(0); if (AZ::EditContext* ec = serialize->GetEditContext()) { - ec->Class("Profiler", "[Description of functionality provided by this System Component]") + ec->Class("Profiler", "Provides a custom implementation of the AZ::Debug::Profiler interface for capturing performance data") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System")) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ; + ->Attribute(AZ::Edit::Attributes::AutoExpand, true); } } + + CpuProfilingStatisticsSerializer::Reflect(context); } void ProfilerSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) { - provided.push_back(AZ_CRC_CE("ProfilerService")); + provided.push_back(profilerServiceCrc); } void ProfilerSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) { - incompatible.push_back(AZ_CRC_CE("ProfilerService")); + incompatible.push_back(profilerServiceCrc); } void ProfilerSystemComponent::GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required) @@ -74,17 +76,14 @@ namespace Profiler void ProfilerSystemComponent::Activate() { ProfilerRequestBus::Handler::BusConnect(); - AZ::TickBus::Handler::BusConnect(); + + m_cpuProfiler.Init(); } void ProfilerSystemComponent::Deactivate() { - AZ::TickBus::Handler::BusDisconnect(); + m_cpuProfiler.Shutdown(); + ProfilerRequestBus::Handler::BusDisconnect(); } - - void ProfilerSystemComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time) - { - } - } // namespace Profiler diff --git a/Gems/Profiler/Code/Source/ProfilerSystemComponent.h b/Gems/Profiler/Code/Source/ProfilerSystemComponent.h index 9b53f7d3a1..65a06145e9 100644 --- a/Gems/Profiler/Code/Source/ProfilerSystemComponent.h +++ b/Gems/Profiler/Code/Source/ProfilerSystemComponent.h @@ -8,16 +8,17 @@ #pragma once -#include -#include #include +#include + +#include + namespace Profiler { class ProfilerSystemComponent : public AZ::Component , protected ProfilerRequestBus::Handler - , public AZ::TickBus::Handler { public: AZ_COMPONENT(ProfilerSystemComponent, "{3f52c1d7-d920-4781-8ed7-88077ec4f305}"); @@ -45,10 +46,8 @@ namespace Profiler void Deactivate() override; //////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////// - // AZTickBus interface implementation - void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; - //////////////////////////////////////////////////////////////////////// + + CpuProfilerImpl m_cpuProfiler; }; } // namespace Profiler diff --git a/Gems/Profiler/Code/profiler_files.cmake b/Gems/Profiler/Code/profiler_files.cmake index f50329b8dc..bd31155b9e 100644 --- a/Gems/Profiler/Code/profiler_files.cmake +++ b/Gems/Profiler/Code/profiler_files.cmake @@ -11,9 +11,6 @@ set(FILES Source/CpuProfiler.h Source/CpuProfilerImpl.cpp Source/CpuProfilerImpl.h - Source/ImGuiCpuProfiler.cpp - Source/ImGuiCpuProfiler.h - Source/ProfilerModuleInterface.h Source/ProfilerSystemComponent.cpp Source/ProfilerSystemComponent.h ) diff --git a/Gems/Profiler/Code/profiler_imgui_shared_files.cmake b/Gems/Profiler/Code/profiler_imgui_shared_files.cmake new file mode 100644 index 0000000000..216f6ceeed --- /dev/null +++ b/Gems/Profiler/Code/profiler_imgui_shared_files.cmake @@ -0,0 +1,15 @@ +# +# 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 +# +# + +set(FILES + Source/ImGuiCpuProfiler.cpp + Source/ImGuiCpuProfiler.h + Source/ProfilerImGuiModule.cpp + Source/ProfilerImGuiSystemComponent.cpp + Source/ProfilerImGuiSystemComponent.h +)