[profiler_capture_api] merging overlapping profiler EBuses into AzCore

Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com>
This commit is contained in:
AMZN-ScottR
2021-10-25 11:45:12 -07:00
parent 4d4deb1211
commit 1f2eaface9
11 changed files with 165 additions and 156 deletions
@@ -9,6 +9,8 @@
#pragma once
#include <AzCore/EBus/EBus.h>
#include <AzCore/Interface/Interface.h>
#include <AzCore/std/string/string.h>
namespace AZ
{
@@ -23,17 +25,13 @@ namespace AZ
public:
virtual ~ProfilerNotifications() = default;
virtual void OnProfileSystemInitialized() = 0;
//! Notify when the current profiler capture is finished
//! @param result Set to true if it's finished successfully
//! @param info The output file path or error information which depends on the return.
virtual void OnCaptureFinished(bool result, const AZStd::string& info) = 0;
};
using ProfilerNotificationBus = AZ::EBus<ProfilerNotifications>;
enum class ProfileFrameAdvanceType
{
Game,
Render,
Default = Game
};
/**
* ProfilerRequests provides an interface for making profiling system requests
*/
@@ -41,14 +39,26 @@ namespace AZ
: public AZ::EBusTraits
{
public:
// EBusTraits overrides
static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
// Allow multiple threads to concurrently make requests
using MutexType = AZStd::mutex;
virtual ~ProfilerRequests() = default;
virtual bool IsActive() = 0;
virtual void FrameAdvance(ProfileFrameAdvanceType type) = 0;
//! Getter/setter for the profiler active state
virtual bool IsActive() const = 0;
virtual void SetActive(bool active) = 0;
//! Capture a single frame of profiling data
virtual bool CaptureFrame(const AZStd::string& outputFilePath) = 0;
//! Starting/ending a multi-frame capture of profiling data
virtual bool StartCapture(const AZStd::string& outputFilePath) = 0;
virtual bool EndCapture() = 0;
};
using ProfilerRequestBus = AZ::EBus<ProfilerRequests>;
}
}
} // namespace Debug
} // namespace AZ
@@ -0,0 +1,70 @@
/*
* 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 <AzCore/Debug/ProfilerBus.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/EditContextConstants.inl>
namespace AZ::Debug
{
class ProfilerNotificationBusHandler final
: public ProfilerNotificationBus::Handler
, public AZ::BehaviorEBusHandler
{
public:
AZ_EBUS_BEHAVIOR_BINDER(ProfilerNotificationBusHandler, "{44161459-B816-4876-95A4-BA16DEC767D6}", AZ::SystemAllocator,
OnCaptureFinished
);
void OnCaptureFinished(bool result, const AZStd::string& info) override
{
Call(FN_OnCaptureFinished, result, info);
}
static void Reflect(AZ::ReflectContext* context)
{
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->EBus<ProfilerNotificationBus>("ProfilerNotificationBus")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation)
->Attribute(AZ::Script::Attributes::Module, "debug")
->Handler<ProfilerNotificationBusHandler>();
}
}
};
void ProfilerReflect(AZ::ReflectContext* context)
{
if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
{
if (AZ::EditContext* ec = serialize->GetEditContext())
{
ProfilerNotificationBusHandler::Reflect(context);
}
}
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->EBus<ProfilerRequestBus>("ProfilerRequestBus")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation)
->Attribute(AZ::Script::Attributes::Module, "debug")
->Event("IsActive", &ProfilerRequestBus::Events::IsActive)
->Event("SetActive", &ProfilerRequestBus::Events::SetActive)
->Event("CaptureFrame", &ProfilerRequestBus::Events::CaptureFrame)
->Event("StartCapture", &ProfilerRequestBus::Events::StartCapture)
->Event("EndCapture", &ProfilerRequestBus::Events::EndCapture);
ProfilerNotificationBusHandler::Reflect(context);
}
}
} // namespace AZ::Debug
@@ -0,0 +1,19 @@
/*
* 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
namespace AZ
{
class ReflectContext;
namespace Debug
{
//! Reflects the profiler bus script bindings
void ProfilerReflect(AZ::ReflectContext* context);
} // namespace Debug
} // namespace AZ
@@ -14,6 +14,7 @@
#include <AzCore/Component/ComponentApplication.h>
#include <AzCore/Component/Entity.h>
#include <AzCore/Component/TickBus.h>
#include <AzCore/Debug/ProfilerReflection.h>
#include <AzCore/Debug/TraceReflection.h>
#include <AzCore/IO/FileIO.h>
#include <AzCore/Math/MathReflection.h>
@@ -925,6 +926,7 @@ void ScriptSystemComponent::Reflect(ReflectContext* reflection)
// reflect default entity
MathReflect(behaviorContext);
ScriptDebug::Reflect(behaviorContext);
Debug::ProfilerReflect(behaviorContext);
Debug::TraceReflect(behaviorContext);
behaviorContext->Class<PlatformID>("Platform")
@@ -106,6 +106,8 @@ set(FILES
Debug/Profiler.inl
Debug/Profiler.h
Debug/ProfilerBus.h
Debug/ProfilerReflection.cpp
Debug/ProfilerReflection.h
Debug/StackTracer.h
Debug/EventTrace.h
Debug/EventTrace.cpp
@@ -1,59 +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 <AzCore/EBus/EBus.h>
#include <AzCore/Interface/Interface.h>
#include <AzCore/std/string/string.h>
namespace Profiler
{
class ProfilerRequests
{
public:
AZ_RTTI(ProfilerRequests, "{3757c4e5-1941-457c-85ae-16305e17a4c6}");
virtual ~ProfilerRequests() = default;
//! Enable/Disable the CpuProfiler
virtual void SetProfilerEnabled(bool enabled) = 0;
//! Dump a single frame of Cpu profiling data
virtual bool CaptureCpuProfilingStatistics(const AZStd::string& outputFilePath) = 0;
//! Start a multiframe capture of CPU profiling data.
virtual bool BeginContinuousCpuProfilingCapture() = 0;
//! End and dump an in-progress continuous capture.
virtual bool EndContinuousCpuProfilingCapture(const AZStd::string& outputFilePath) = 0;
};
class ProfilerBusTraits
: public AZ::EBusTraits
{
public:
// EBusTraits overrides
static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
};
class ProfilerNotifications
: public AZ::EBusTraits
{
public:
virtual ~ProfilerNotifications() = default;
//! Notify when the current CpuProfilingStatistics capture is finished
//! @param result Set to true if it's finished successfully
//! @param info The output file path or error information which depends on the return.
virtual void OnCaptureCpuProfilingStatisticsFinished(bool result, const AZStd::string& info) = 0;
};
using ProfilerInterface = AZ::Interface<ProfilerRequests>;
using ProfilerRequestBus = AZ::EBus<ProfilerRequests, ProfilerBusTraits>;
using ProfilerNotificationBus = AZ::EBus<ProfilerNotifications>;
} // namespace Profiler
+24 -23
View File
@@ -10,9 +10,9 @@
#include <ImGuiCpuProfiler.h>
#include <Profiler/ProfilerBus.h>
#include <CpuProfilerImpl.h>
#include <AzCore/Debug/ProfilerBus.h>
#include <AzCore/IO/FileIO.h>
#include <AzCore/JSON/filereadstream.h>
#include <AzCore/Outcome/Outcome.h>
@@ -156,16 +156,10 @@ namespace Profiler
if (m_captureToFile)
{
AZStd::string timeString;
AZStd::to_string(timeString, AZStd::GetTimeNowSecond());
const AZStd::string frameDataFilePath = AZStd::string::format("%s/cpu_single_%s.json", defaultSaveLocation, timeString.c_str());
char resolvedPath[AZ::IO::MaxPathLength];
AZ::IO::FileIOBase::GetInstance()->ResolvePath(frameDataFilePath.c_str(), resolvedPath, AZ::IO::MaxPathLength);
m_lastCapturedFilePath = resolvedPath;
ProfilerRequestBus::Broadcast(&ProfilerRequestBus::Events::CaptureCpuProfilingStatistics, frameDataFilePath);
AZ::Debug::ProfilerRequestBus::Broadcast(
&AZ::Debug::ProfilerRequestBus::Events::CaptureFrame,
GenerateOutputFile("single")
);
}
m_captureToFile = false;
@@ -208,22 +202,15 @@ namespace Profiler
{
if (isInProgress)
{
AZStd::string timeString;
AZStd::to_string(timeString, AZStd::GetTimeNowSecond());
const AZStd::string frameDataFilePath = AZStd::string::format("%s/cpu_multi_%s.json", defaultSaveLocation, timeString.c_str());
char resolvedPath[AZ::IO::MaxPathLength];
AZ::IO::FileIOBase::GetInstance()->ResolvePath(frameDataFilePath.c_str(), resolvedPath, AZ::IO::MaxPathLength);
m_lastCapturedFilePath = resolvedPath;
ProfilerRequestBus::Broadcast(&ProfilerRequestBus::Events::EndContinuousCpuProfilingCapture, frameDataFilePath);
AZ::Debug::ProfilerRequestBus::Broadcast(&AZ::Debug::ProfilerRequestBus::Events::EndCapture);
m_paused = true;
}
else
{
ProfilerRequestBus::Broadcast(&ProfilerRequestBus::Events::BeginContinuousCpuProfilingCapture);
AZ::Debug::ProfilerRequestBus::Broadcast(
&AZ::Debug::ProfilerRequestBus::Events::StartCapture,
GenerateOutputFile("multi")
);
}
}
@@ -418,6 +405,20 @@ namespace Profiler
ImGui::End();
}
AZStd::string ImGuiCpuProfiler::GenerateOutputFile(const char* nameHint)
{
AZStd::string timeString;
AZStd::to_string(timeString, AZStd::GetTimeNowSecond());
const AZStd::string frameDataFilePath = AZStd::string::format("%s/cpu_%s_%s.json", defaultSaveLocation, nameHint, timeString.c_str());
char resolvedPath[AZ::IO::MaxPathLength];
AZ::IO::FileIOBase::GetInstance()->ResolvePath(frameDataFilePath.c_str(), resolvedPath, AZ::IO::MaxPathLength);
m_lastCapturedFilePath = resolvedPath;
return frameDataFilePath;
}
void ImGuiCpuProfiler::LoadFile()
{
const AZ::IO::Path& pathToLoad = m_cachedCapturePaths[m_currentFileIndex];
@@ -107,6 +107,9 @@ namespace Profiler
//! Draws the statistical view of the CPU profiling data.
void DrawStatisticsView();
//! Generates the full output timestamped file path based on nameHint
AZStd::string GenerateOutputFile(const char* nameHint);
//! Callback invoked when the "Load File" button is pressed in the file picker.
void LoadFile();
@@ -51,32 +51,6 @@ namespace Profiler
int m_framesLeft{ 0 };
};
class ProfilerNotificationBusHandler final
: public ProfilerNotificationBus::Handler
, public AZ::BehaviorEBusHandler
{
public:
AZ_EBUS_BEHAVIOR_BINDER(ProfilerNotificationBusHandler, "{44161459-B816-4876-95A4-BA16DEC767D6}", AZ::SystemAllocator,
OnCaptureCpuProfilingStatisticsFinished
);
void OnCaptureCpuProfilingStatisticsFinished(bool result, const AZStd::string& info) override
{
Call(FN_OnCaptureCpuProfilingStatisticsFinished, result, info);
}
static void Reflect(AZ::ReflectContext* context)
{
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->EBus<ProfilerNotificationBus>("ProfilerNotificationBus")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation)
->Attribute(AZ::Script::Attributes::Module, "profiler")
->Handler<ProfilerNotificationBusHandler>();
}
}
};
bool SerializeCpuProfilingData(const AZStd::ring_buffer<CpuProfiler::TimeRegionMap>& data, AZStd::string outputFilePath, bool wasEnabled)
{
AZ_TracePrintf("ProfilerSystemComponent", "Beginning serialization of %zu frames of profiling data\n", data.size());
@@ -107,8 +81,8 @@ namespace Profiler
CpuProfiler::Get()->SetProfilerEnabled(false);
}
// Notify listeners that the pass' PipelineStatistics queries capture has finished.
ProfilerNotificationBus::Broadcast(&ProfilerNotificationBus::Events::OnCaptureCpuProfilingStatisticsFinished,
// Notify listeners that the profiler capture has finished.
AZ::Debug::ProfilerNotificationBus::Broadcast(&AZ::Debug::ProfilerNotificationBus::Events::OnCaptureFinished,
saveResult.IsSuccess(),
captureInfo);
@@ -128,21 +102,9 @@ namespace Profiler
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("System"))
->Attribute(AZ::Edit::Attributes::AutoExpand, true);
ProfilerNotificationBusHandler::Reflect(context);
}
}
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->EBus<ProfilerRequestBus>("ProfilerRequestBus")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation)
->Attribute(AZ::Script::Attributes::Module, "profiler")
->Event("CaptureCpuProfilingStatistics", &ProfilerRequestBus::Events::CaptureCpuProfilingStatistics);
ProfilerNotificationBusHandler::Reflect(context);
}
CpuProfilingStatisticsSerializer::Reflect(context);
}
@@ -166,23 +128,15 @@ namespace Profiler
ProfilerSystemComponent::ProfilerSystemComponent()
{
if (ProfilerInterface::Get() == nullptr)
{
ProfilerInterface::Register(this);
}
}
ProfilerSystemComponent::~ProfilerSystemComponent()
{
if (ProfilerInterface::Get() == this)
{
ProfilerInterface::Unregister(this);
}
}
void ProfilerSystemComponent::Activate()
{
ProfilerRequestBus::Handler::BusConnect();
AZ::Debug::ProfilerRequestBus::Handler::BusConnect();
m_cpuProfiler.Init();
}
@@ -191,7 +145,7 @@ namespace Profiler
{
m_cpuProfiler.Shutdown();
ProfilerRequestBus::Handler::BusDisconnect();
AZ::Debug::ProfilerRequestBus::Handler::BusDisconnect();
// Block deactivation until the IO thread has finished serializing the CPU data
if (m_cpuDataSerializationThread.joinable())
@@ -200,12 +154,17 @@ namespace Profiler
}
}
void ProfilerSystemComponent::SetProfilerEnabled(bool enabled)
bool ProfilerSystemComponent::IsActive() const
{
return m_cpuProfiler.IsProfilerEnabled();
}
void ProfilerSystemComponent::SetActive(bool enabled)
{
m_cpuProfiler.SetProfilerEnabled(enabled);
}
bool ProfilerSystemComponent::CaptureCpuProfilingStatistics(const AZStd::string& outputFilePath)
bool ProfilerSystemComponent::CaptureFrame(const AZStd::string& outputFilePath)
{
bool expected = false;
if (!m_cpuCaptureInProgress.compare_exchange_strong(expected, true))
@@ -236,12 +195,13 @@ namespace Profiler
return true;
}
bool ProfilerSystemComponent::BeginContinuousCpuProfilingCapture()
bool ProfilerSystemComponent::StartCapture(const AZStd::string& outputFilePath)
{
m_captureFile = outputFilePath;
return m_cpuProfiler.BeginContinuousCapture();
}
bool ProfilerSystemComponent::EndContinuousCpuProfilingCapture(const AZStd::string& outputFilePath)
bool ProfilerSystemComponent::EndCapture()
{
bool expected = false;
if (!m_cpuDataSerializationInProgress.compare_exchange_strong(expected, true))
@@ -263,7 +223,7 @@ namespace Profiler
// cpuProfilingData could be 1GB+ once saved, so use an IO thread to write it to disk.
auto threadIoFunction =
[data = AZStd::move(captureResult), filePath = AZStd::string(outputFilePath), &flag = m_cpuDataSerializationInProgress]()
[data = AZStd::move(captureResult), filePath = m_captureFile, &flag = m_cpuDataSerializationInProgress]()
{
SerializeCpuProfilingData(data, filePath, true);
flag.store(false);
@@ -8,17 +8,17 @@
#pragma once
#include <Profiler/ProfilerBus.h>
#include <CpuProfilerImpl.h>
#include <AzCore/Component/Component.h>
#include <AzCore/Debug/ProfilerBus.h>
#include <AzCore/std/parallel/thread.h>
namespace Profiler
{
class ProfilerSystemComponent
: public AZ::Component
, protected ProfilerRequestBus::Handler
, protected AZ::Debug::ProfilerRequestBus::Handler
{
public:
AZ_COMPONENT(ProfilerSystemComponent, "{3f52c1d7-d920-4781-8ed7-88077ec4f305}");
@@ -39,10 +39,11 @@ namespace Profiler
void Deactivate() override;
// ProfilerRequestBus interface implementation
void SetProfilerEnabled(bool enabled) override;
bool CaptureCpuProfilingStatistics(const AZStd::string& outputFilePath) override;
bool BeginContinuousCpuProfilingCapture() override;
bool EndContinuousCpuProfilingCapture(const AZStd::string& outputFilePath) override;
bool IsActive() const override;
void SetActive(bool active) override;
bool CaptureFrame(const AZStd::string& outputFilePath) override;
bool StartCapture(const AZStd::string& outputFilePath) override;
bool EndCapture() override;
AZStd::thread m_cpuDataSerializationThread;
@@ -51,6 +52,7 @@ namespace Profiler
AZStd::atomic_bool m_cpuCaptureInProgress{ false };
CpuProfilerImpl m_cpuProfiler;
AZStd::string m_captureFile;
};
} // namespace Profiler
-1
View File
@@ -7,7 +7,6 @@
#
set(FILES
Include/Profiler/ProfilerBus.h
Include/Profiler/ProfilerImGuiBus.h
Source/CpuProfiler.h
Source/CpuProfilerImpl.cpp