[development] Migrate Atom CPU timing stats tracking to use global stats profiler (#4549)
This change is a preparation for moving the CPU profiler/visualization system from Atom into its own Gem by removing the dependency on local time tracking object AZ::RHI::CpuTimingStatistics Full changes include: - Removed all usage of AZ::RHI::CpuTimingStatistics -- Replaced with pushing to AZ::Statistics::StatisticalProfilerProxy global instance - Promoted VariableTimer from AZ::RHI to AZ::Debug - Removed now unused CpuTimingStatistics.h Signed-off-by: AMZN-ScottR 24445312+AMZN-ScottR@users.noreply.github.com
This commit is contained in:
@@ -46,5 +46,23 @@ namespace AZ
|
||||
private:
|
||||
AZStd::sys_time_t m_timeStamp;
|
||||
};
|
||||
|
||||
//! Utility type that updates the given variable with the lifetime of the object in cycles.
|
||||
//! Useful for quick scope based timing.
|
||||
struct ScopedTimer
|
||||
{
|
||||
explicit ScopedTimer(AZStd::sys_time_t& variable)
|
||||
: m_variable(variable)
|
||||
{
|
||||
m_timer.Stamp();
|
||||
}
|
||||
~ScopedTimer()
|
||||
{
|
||||
m_variable = m_timer.GetDeltaTimeInTicks();
|
||||
}
|
||||
|
||||
AZStd::sys_time_t& m_variable;
|
||||
Timer m_timer;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <Atom/RHI/CpuProfilerImpl.h>
|
||||
#include <Atom/RHI/RHIUtils.h>
|
||||
#include <Atom/RHI/RHISystemInterface.h>
|
||||
#include <Atom/RHI.Reflect/CpuTimingStatistics.h>
|
||||
#include <AzCore/Statistics/RunningStatistic.h>
|
||||
|
||||
#include <Atom/RPI.Public/GpuQuery/GpuQueryTypes.h>
|
||||
@@ -457,17 +456,8 @@ namespace AZ
|
||||
JsonSerializerSettings serializationSettings;
|
||||
serializationSettings.m_keepDefaults = true;
|
||||
|
||||
double frameTime = 0.0;
|
||||
const AZ::RHI::CpuTimingStatistics* stats = AZ::RHI::RHISystemInterface::Get()->GetCpuTimingStatistics();
|
||||
if (stats)
|
||||
{
|
||||
frameTime = stats->GetFrameToFrameTimeMilliseconds();
|
||||
}
|
||||
else
|
||||
{
|
||||
AZStd::string warning = AZStd::string::format("Failed to get Cpu frame time");
|
||||
AZ_Warning("ProfilingCaptureSystemComponent", false, warning.c_str());
|
||||
}
|
||||
double frameTime = AZ::RHI::RHISystemInterface::Get()->GetCpuFrameTime();
|
||||
AZ_Warning("ProfilingCaptureSystemComponent", frameTime > 0, "Failed to get Cpu frame time");
|
||||
|
||||
CpuFrameTimeSerializer serializer(frameTime);
|
||||
const auto saveResult = JsonSerializationUtils::SaveObjectToFile(&serializer,
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <AzCore/std/smart_ptr/intrusive_ptr.h>
|
||||
|
||||
AZ_DECLARE_BUDGET(RHI);
|
||||
inline static constexpr AZ::Crc32 rhiMetricsId = AZ_CRC_CE("RHI");
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
|
||||
@@ -1,77 +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 <Atom/RHI.Reflect/AttachmentEnums.h>
|
||||
|
||||
#include <AzCore/Debug/Timer.h>
|
||||
#include <AzCore/Name/Name.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace RHI
|
||||
{
|
||||
//! Container and helper type for storing per frame CPU timing data.
|
||||
//! Users can queue up generic timings in Scopes or add to specific timing data.
|
||||
struct CpuTimingStatistics
|
||||
{
|
||||
struct QueueStatistics
|
||||
{
|
||||
//! The display name of the queue the statistics are for.
|
||||
Name m_queueName;
|
||||
|
||||
//! Time spent executing queued work.
|
||||
AZStd::sys_time_t m_executeDuration{};
|
||||
};
|
||||
|
||||
//! Statistics for each command queue.
|
||||
AZStd::vector<QueueStatistics> m_queueStatistics;
|
||||
|
||||
//! The amount of time spent between two calls to EndFrame.
|
||||
AZStd::sys_time_t m_frameToFrameTime{};
|
||||
|
||||
//! The amount of time spent presenting (vsync can affect this).
|
||||
AZStd::sys_time_t m_presentDuration{};
|
||||
|
||||
void Reset()
|
||||
{
|
||||
m_queueStatistics.clear();
|
||||
}
|
||||
|
||||
double GetFrameToFrameTimeMilliseconds() const
|
||||
{
|
||||
return (m_frameToFrameTime * 1000) / aznumeric_cast<double>(AZStd::GetTimeTicksPerSecond());
|
||||
}
|
||||
};
|
||||
|
||||
//! Utility type that updates the given variable with the lifetime of the object in cycles.
|
||||
//! Useful for quick scope based timing.
|
||||
struct VariableTimer
|
||||
{
|
||||
VariableTimer() = delete;
|
||||
VariableTimer(AZStd::sys_time_t& variable)
|
||||
: m_variable(variable)
|
||||
{
|
||||
m_timer.Stamp();
|
||||
}
|
||||
~VariableTimer()
|
||||
{
|
||||
m_variable = m_timer.GetDeltaTimeInTicks();
|
||||
}
|
||||
|
||||
AZStd::sys_time_t& m_variable;
|
||||
AZ::Debug::Timer m_timer;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
//! Utility for timing a section of code and writing the timing (in cycles) to the given variable.
|
||||
#define AZ_PROFILE_RHI_VARIABLE(variable) \
|
||||
AZ::RHI::VariableTimer AZ_JOIN(variableTimer, __LINE__)(variable);
|
||||
@@ -27,9 +27,6 @@ namespace AZ
|
||||
{
|
||||
namespace RHI
|
||||
{
|
||||
struct CpuTimingStatistics;
|
||||
|
||||
|
||||
//! The Device is a context for managing GPU state and memory on a physical device. The user creates
|
||||
//! a device instance from a PhysicalDevice. Each device has its own capabilities and limits, and can
|
||||
//! be configured to buffer a specific number of frames.
|
||||
@@ -91,10 +88,10 @@ namespace AZ
|
||||
//! scope. Otherwise, an error code is returned.
|
||||
ResultCode CompileMemoryStatistics(MemoryStatistics& memoryStatistics, MemoryStatisticsReportFlags reportFlags);
|
||||
|
||||
//! Fills the provided data structure with cpu timing statistics specific to this device. This
|
||||
//! method can only be called on an initialized device, and outside of the BeginFrame / EndFrame
|
||||
//! scope. Otherwise, an error code is returned.
|
||||
ResultCode UpdateCpuTimingStatistics(CpuTimingStatistics& cpuTimingStatistics) const;
|
||||
//! Pushes internally recorded timing statistics upwards into the global stats profiler, under the RHI section.
|
||||
//! This method can only be called on an initialized device, and outside of the BeginFrame / EndFrame scope.
|
||||
//! Otherwise, an error code is returned.
|
||||
ResultCode UpdateCpuTimingStatistics() const;
|
||||
|
||||
//! Returns the physical device associated with this device.
|
||||
const PhysicalDevice& GetPhysicalDevice() const;
|
||||
@@ -186,7 +183,7 @@ namespace AZ
|
||||
virtual void CompileMemoryStatisticsInternal(MemoryStatisticsBuilder& builder) = 0;
|
||||
|
||||
//! Called when the device is reporting cpu timing statistics.
|
||||
virtual void UpdateCpuTimingStatisticsInternal(CpuTimingStatistics& cpuTimingStatistics) const = 0;
|
||||
virtual void UpdateCpuTimingStatisticsInternal() const = 0;
|
||||
|
||||
//! Fills the capabilities for each format.
|
||||
virtual void FillFormatsCapabilitiesInternal(FormatCapabilitiesList& formatsCapabilities) = 0;
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <Atom/RHI.Reflect/CpuTimingStatistics.h>
|
||||
#include <Atom/RHI.Reflect/FrameSchedulerEnums.h>
|
||||
#include <Atom/RHI.Reflect/MemoryStatistics.h>
|
||||
#include <Atom/RHI/FrameGraphBuilder.h>
|
||||
@@ -168,8 +167,8 @@ namespace AZ
|
||||
/// Returns the timing statistics for the previous frame.
|
||||
const TransientAttachmentStatistics* GetTransientAttachmentStatistics() const;
|
||||
|
||||
/// Returns cpu timing statistics for the previous frame.
|
||||
const CpuTimingStatistics* GetCpuTimingStatistics() const;
|
||||
/// Returns current CPU frame to frame time in milliseconds.
|
||||
double GetCpuFrameTime() const;
|
||||
|
||||
/// Returns memory statistics for the previous frame.
|
||||
const MemoryStatistics* GetMemoryStatistics() const;
|
||||
@@ -216,7 +215,6 @@ namespace AZ
|
||||
|
||||
Ptr<TransientAttachmentPool> m_transientAttachmentPool;
|
||||
|
||||
CpuTimingStatistics m_cpuTimingStatistics;
|
||||
AZStd::sys_time_t m_lastFrameEndTime{};
|
||||
MemoryStatistics m_memoryStatistics;
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace AZ
|
||||
RHI::PipelineStateCache* GetPipelineStateCache() override;
|
||||
const RHI::FrameSchedulerCompileRequest& GetFrameSchedulerCompileRequest() const override;
|
||||
void ModifyFrameSchedulerStatisticsFlags(RHI::FrameSchedulerStatisticsFlags statisticsFlags, bool enableFlags) override;
|
||||
const RHI::CpuTimingStatistics* GetCpuTimingStatistics() const override;
|
||||
double GetCpuFrameTime() const override;
|
||||
const RHI::TransientAttachmentStatistics* GetTransientAttachmentStatistics() const override;
|
||||
const RHI::MemoryStatistics* GetMemoryStatistics() const override;
|
||||
const RHI::TransientAttachmentPoolDescriptor* GetTransientAttachmentPoolDescriptor() const override;
|
||||
|
||||
@@ -27,7 +27,6 @@ namespace AZ
|
||||
class PipelineStateCache;
|
||||
class PlatformLimitsDescriptor;
|
||||
class RayTracingShaderTable;
|
||||
struct CpuTimingStatistics;
|
||||
struct FrameSchedulerCompileRequest;
|
||||
struct TransientAttachmentStatistics;
|
||||
struct TransientAttachmentPoolDescriptor;
|
||||
@@ -55,7 +54,7 @@ namespace AZ
|
||||
|
||||
virtual void ModifyFrameSchedulerStatisticsFlags(RHI::FrameSchedulerStatisticsFlags statisticsFlags, bool enableFlags) = 0;
|
||||
|
||||
virtual const RHI::CpuTimingStatistics* GetCpuTimingStatistics() const = 0;
|
||||
virtual double GetCpuFrameTime() const = 0;
|
||||
|
||||
virtual const RHI::TransientAttachmentStatistics* GetTransientAttachmentStatistics() const = 0;
|
||||
|
||||
|
||||
@@ -32,6 +32,23 @@ namespace AZ
|
||||
return ResultCode::InvalidOperation;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (auto statsProfiler = AZ::Interface<AZ::Statistics::StatisticalProfilerProxy>::Get(); statsProfiler)
|
||||
{
|
||||
auto& rhiMetrics = statsProfiler->GetProfiler(rhiMetricsId);
|
||||
|
||||
static constexpr AZStd::string_view presentStatName("Present");
|
||||
static constexpr AZ::Crc32 presentStatId(presentStatName);
|
||||
rhiMetrics.GetStatsManager().AddStatistic(presentStatId, presentStatName, /*units=*/"clocks", /*failIfExist=*/false);
|
||||
|
||||
if (!GetName().IsEmpty())
|
||||
{
|
||||
const AZStd::string commandQueueName(GetName().GetCStr());
|
||||
const AZ::Crc32 commandQueueId(GetName().GetHash());
|
||||
rhiMetrics.GetStatsManager().AddStatistic(commandQueueId, commandQueueName, /*units=*/"clocks", /*failIfExist=*/false);
|
||||
}
|
||||
}
|
||||
|
||||
const ResultCode resultCode = InitInternal(device, descriptor);
|
||||
|
||||
if (resultCode == ResultCode::Success)
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <AzCore/std/smart_ptr/shared_ptr.h>
|
||||
|
||||
#include <AzCore/Debug/Timer.h>
|
||||
#include <AzCore/Statistics/StatisticalProfilerProxy.h>
|
||||
#include <Atom/RHI/RHIUtils.h>
|
||||
|
||||
namespace AZ
|
||||
@@ -73,6 +74,11 @@ namespace AZ
|
||||
m_initialized = true;
|
||||
SystemTickBus::Handler::BusConnect();
|
||||
m_continuousCaptureData.set_capacity(10);
|
||||
|
||||
if (auto statsProfiler = AZ::Interface<AZ::Statistics::StatisticalProfilerProxy>::Get(); statsProfiler)
|
||||
{
|
||||
statsProfiler->ActivateProfiler(AZ_CRC_CE("RHI"), true);
|
||||
}
|
||||
}
|
||||
|
||||
void CpuProfilerImpl::Shutdown()
|
||||
|
||||
@@ -160,11 +160,11 @@ namespace AZ
|
||||
return ResultCode::InvalidOperation;
|
||||
}
|
||||
|
||||
ResultCode Device::UpdateCpuTimingStatistics(CpuTimingStatistics& cpuTimingStatistics) const
|
||||
ResultCode Device::UpdateCpuTimingStatistics() const
|
||||
{
|
||||
if (ValidateIsNotInFrame())
|
||||
{
|
||||
UpdateCpuTimingStatisticsInternal(cpuTimingStatistics);
|
||||
UpdateCpuTimingStatisticsInternal();
|
||||
return ResultCode::Success;
|
||||
}
|
||||
return ResultCode::InvalidOperation;
|
||||
|
||||
@@ -35,6 +35,9 @@ namespace AZ
|
||||
{
|
||||
namespace RHI
|
||||
{
|
||||
static constexpr const char* frameTimeMetricName = "Frame to Frame Time";
|
||||
static constexpr AZ::Crc32 frameTimeMetricId = AZ_CRC_CE(frameTimeMetricName);
|
||||
|
||||
ResultCode FrameScheduler::Init(Device& device, const FrameSchedulerDescriptor& descriptor)
|
||||
{
|
||||
ResultCode resultCode = ResultCode::Success;
|
||||
@@ -81,6 +84,12 @@ namespace AZ
|
||||
|
||||
m_taskGraphActive = AZ::Interface<AZ::TaskGraphActiveInterface>::Get();
|
||||
|
||||
if (auto statsProfiler = AZ::Interface<AZ::Statistics::StatisticalProfilerProxy>::Get(); statsProfiler)
|
||||
{
|
||||
auto& rhiMetrics = statsProfiler->GetProfiler(rhiMetricsId);
|
||||
rhiMetrics.GetStatsManager().AddStatistic(frameTimeMetricId, frameTimeMetricName, /*units=*/"clocks", /*failIfExist=*/false);
|
||||
}
|
||||
|
||||
m_lastFrameEndTime = AZStd::GetTimeNowTicks();
|
||||
|
||||
return ResultCode::Success;
|
||||
@@ -278,7 +287,7 @@ namespace AZ
|
||||
AZ::TaskDescriptor srgCompileEndDesc{"SrgCompileEnd", "Graphics"};
|
||||
|
||||
auto srgCompileEndTask = taskGraph.AddTask(
|
||||
srgCompileEndDesc,
|
||||
srgCompileEndDesc,
|
||||
[srgPool]()
|
||||
{
|
||||
srgPool->CompileGroupsEnd();
|
||||
@@ -449,7 +458,7 @@ namespace AZ
|
||||
m_device->CompileMemoryStatistics(m_memoryStatistics, MemoryStatisticsReportFlags::Detail);
|
||||
}
|
||||
|
||||
m_device->UpdateCpuTimingStatistics(m_cpuTimingStatistics);
|
||||
m_device->UpdateCpuTimingStatistics();
|
||||
|
||||
m_scopeProducers.clear();
|
||||
m_scopeProducerLookup.clear();
|
||||
@@ -460,7 +469,10 @@ namespace AZ
|
||||
}
|
||||
|
||||
const AZStd::sys_time_t timeNowTicks = AZStd::GetTimeNowTicks();
|
||||
m_cpuTimingStatistics.m_frameToFrameTime = timeNowTicks - m_lastFrameEndTime;
|
||||
if (auto statsProfiler = AZ::Interface<AZ::Statistics::StatisticalProfilerProxy>::Get(); statsProfiler)
|
||||
{
|
||||
statsProfiler->PushSample(rhiMetricsId, frameTimeMetricId, static_cast<double>(timeNowTicks - m_lastFrameEndTime));
|
||||
}
|
||||
m_lastFrameEndTime = timeNowTicks;
|
||||
|
||||
return ResultCode::Success;
|
||||
@@ -588,12 +600,18 @@ namespace AZ
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
const CpuTimingStatistics* FrameScheduler::GetCpuTimingStatistics() const
|
||||
double FrameScheduler::GetCpuFrameTime() const
|
||||
{
|
||||
return
|
||||
CheckBitsAny(m_compileRequest.m_statisticsFlags, FrameSchedulerStatisticsFlags::GatherCpuTimingStatistics)
|
||||
? &m_cpuTimingStatistics
|
||||
: nullptr;
|
||||
if (CheckBitsAny(m_compileRequest.m_statisticsFlags, FrameSchedulerStatisticsFlags::GatherCpuTimingStatistics))
|
||||
{
|
||||
if (auto statsProfiler = AZ::Interface<AZ::Statistics::StatisticalProfilerProxy>::Get(); statsProfiler)
|
||||
{
|
||||
auto& rhiMetrics = statsProfiler->GetProfiler(rhiMetricsId);
|
||||
const auto* frameTimeStat = rhiMetrics.GetStatistic(frameTimeMetricId);
|
||||
return (frameTimeStat->GetMostRecentSample() * 1000) / aznumeric_cast<double>(AZStd::GetTimeTicksPerSecond());
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ScopeId FrameScheduler::GetRootScopeId() const
|
||||
|
||||
@@ -254,9 +254,9 @@ namespace AZ
|
||||
: RHI::ResetBits(m_compileRequest.m_statisticsFlags, statisticsFlags);
|
||||
}
|
||||
|
||||
const RHI::CpuTimingStatistics* RHISystem::GetCpuTimingStatistics() const
|
||||
double RHISystem::GetCpuFrameTime() const
|
||||
{
|
||||
return m_frameScheduler.GetCpuTimingStatistics();
|
||||
return m_frameScheduler.GetCpuFrameTime();
|
||||
}
|
||||
|
||||
const RHI::TransientAttachmentStatistics* RHISystem::GetTransientAttachmentStatistics() const
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace UnitTest
|
||||
|
||||
void CompileMemoryStatisticsInternal(AZ::RHI::MemoryStatisticsBuilder&) override {}
|
||||
|
||||
void UpdateCpuTimingStatisticsInternal([[maybe_unused]] AZ::RHI::CpuTimingStatistics& cpuTimingStatistics) const override {}
|
||||
void UpdateCpuTimingStatisticsInternal() const override {}
|
||||
|
||||
AZStd::chrono::microseconds GpuTimestampToMicroseconds([[maybe_unused]] uint64_t gpuTimestamp, [[maybe_unused]] AZ::RHI::HardwareQueueClass queueClass) const override
|
||||
{
|
||||
|
||||
@@ -112,7 +112,6 @@ set(FILES
|
||||
Source/RHI.Reflect/ShaderResourceGroupLayout.cpp
|
||||
Source/RHI.Reflect/ShaderResourceGroupLayoutDescriptor.cpp
|
||||
Source/RHI.Reflect/ShaderResourceGroupPoolDescriptor.cpp
|
||||
Include/Atom/RHI.Reflect/CpuTimingStatistics.h
|
||||
Include/Atom/RHI.Reflect/MemoryStatistics.h
|
||||
Include/Atom/RHI.Reflect/TransientAttachmentStatistics.h
|
||||
Include/Atom/RHI.Reflect/SwapChainDescriptor.h
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
#include <RHI/Fence.h>
|
||||
#include <RHI/SwapChain.h>
|
||||
#include <RHI/Conversions.h>
|
||||
#include <AzCore/Debug/EventTraceDrillerBus.h>
|
||||
#include <Atom/RHI.Reflect/CpuTimingStatistics.h>
|
||||
|
||||
#include <AzCore/Debug/Timer.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -139,7 +139,7 @@ namespace AZ
|
||||
QueueCommand([=](void* commandQueue)
|
||||
{
|
||||
AZ_PROFILE_SCOPE(RHI, "ExecuteWork");
|
||||
AZ_PROFILE_RHI_VARIABLE(m_lastExecuteDuration);
|
||||
AZ::Debug::ScopedTimer executionTimer(m_lastExecuteDuration);
|
||||
|
||||
static const uint32_t CommandListCountMax = 128;
|
||||
ID3D12CommandQueue* dx12CommandQueue = static_cast<ID3D12CommandQueue*>(commandQueue);
|
||||
@@ -185,7 +185,7 @@ namespace AZ
|
||||
dx12CommandQueue->Signal(fence->Get(), fence->GetPendingValue());
|
||||
}
|
||||
|
||||
AZ_PROFILE_RHI_VARIABLE(m_lastPresentDuration);
|
||||
AZ::Debug::ScopedTimer presentTimer(m_lastPresentDuration);
|
||||
for (RHI::SwapChain* swapChain : request.m_swapChainsToPresent)
|
||||
{
|
||||
swapChain->Present();
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
*/
|
||||
|
||||
#include <Atom/RHI/Device.h>
|
||||
#include <Atom/RHI.Reflect/CpuTimingStatistics.h>
|
||||
#include <AzCore/Debug/EventTraceDrillerBus.h>
|
||||
#include <RHI/CommandQueueContext.h>
|
||||
#include <RHI/Device.h>
|
||||
@@ -183,17 +182,22 @@ namespace AZ
|
||||
return *m_commandQueues[static_cast<uint32_t>(hardwareQueueClass)];
|
||||
}
|
||||
|
||||
void CommandQueueContext::UpdateCpuTimingStatistics(RHI::CpuTimingStatistics& cpuTimingStatistics) const
|
||||
void CommandQueueContext::UpdateCpuTimingStatistics() const
|
||||
{
|
||||
cpuTimingStatistics.Reset();
|
||||
|
||||
AZStd::sys_time_t presentDuration = 0;
|
||||
for (const RHI::Ptr<CommandQueue>& commandQueue : m_commandQueues)
|
||||
if (auto statsProfiler = AZ::Interface<AZ::Statistics::StatisticalProfilerProxy>::Get(); statsProfiler)
|
||||
{
|
||||
cpuTimingStatistics.m_queueStatistics.push_back({ commandQueue->GetName(), commandQueue->GetLastExecuteDuration() });
|
||||
presentDuration += commandQueue->GetLastPresentDuration();
|
||||
auto& rhiMetrics = statsProfiler->GetProfiler(rhiMetricsId);
|
||||
|
||||
AZStd::sys_time_t presentDuration = 0;
|
||||
for (const RHI::Ptr<CommandQueue>& commandQueue : m_commandQueues)
|
||||
{
|
||||
const AZ::Crc32 commandQueueId(commandQueue->GetName().GetHash());
|
||||
rhiMetrics.PushSample(commandQueueId, static_cast<double>(commandQueue->GetLastExecuteDuration()));
|
||||
presentDuration += commandQueue->GetLastPresentDuration();
|
||||
}
|
||||
|
||||
rhiMetrics.PushSample(AZ_CRC_CE("Present"), static_cast<double>(presentDuration));
|
||||
}
|
||||
cpuTimingStatistics.m_presentDuration = presentDuration;
|
||||
}
|
||||
|
||||
const FenceSet& CommandQueueContext::GetCompiledFences()
|
||||
|
||||
@@ -14,11 +14,6 @@
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace RHI
|
||||
{
|
||||
struct CpuTimingStatistics;
|
||||
}
|
||||
|
||||
namespace DX12
|
||||
{
|
||||
class CommandQueueContext
|
||||
@@ -49,7 +44,7 @@ namespace AZ
|
||||
RHI::HardwareQueueClass hardwareQueueClass,
|
||||
const ExecuteWorkRequest& request);
|
||||
|
||||
void UpdateCpuTimingStatistics(RHI::CpuTimingStatistics& cpuTimingStatistics) const;
|
||||
void UpdateCpuTimingStatistics() const;
|
||||
|
||||
// Fences across all queues that are compiled by the frame graph compilation phase
|
||||
const FenceSet& GetCompiledFences();
|
||||
|
||||
@@ -184,9 +184,9 @@ namespace AZ
|
||||
m_stagingMemoryAllocator.ReportMemoryUsage(builder);
|
||||
}
|
||||
|
||||
void Device::UpdateCpuTimingStatisticsInternal(RHI::CpuTimingStatistics& cpuTimingStatistics) const
|
||||
void Device::UpdateCpuTimingStatisticsInternal() const
|
||||
{
|
||||
m_commandQueueContext.UpdateCpuTimingStatistics(cpuTimingStatistics);
|
||||
m_commandQueueContext.UpdateCpuTimingStatistics();
|
||||
}
|
||||
|
||||
void Device::EndFrameInternal()
|
||||
|
||||
@@ -147,7 +147,7 @@ namespace AZ
|
||||
|
||||
void ShutdownInternal() override;
|
||||
void CompileMemoryStatisticsInternal(RHI::MemoryStatisticsBuilder& builder) override;
|
||||
void UpdateCpuTimingStatisticsInternal(RHI::CpuTimingStatistics& cpuTimingStatistics) const override;
|
||||
void UpdateCpuTimingStatisticsInternal() const override;
|
||||
void BeginFrameInternal() override;
|
||||
void EndFrameInternal() override;
|
||||
void WaitForIdleInternal() override;
|
||||
|
||||
@@ -5,14 +5,15 @@
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
#include <Atom/RHI.Reflect/CpuTimingStatistics.h>
|
||||
#include <AzCore/Debug/EventTrace.h>
|
||||
|
||||
#include <RHI/CommandQueue.h>
|
||||
#include <RHI/Conversions.h>
|
||||
#include <RHI/Device.h>
|
||||
#include <RHI/Fence.h>
|
||||
#include <RHI/SwapChain.h>
|
||||
|
||||
#include <AzCore/Debug/Timer.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Metal
|
||||
@@ -115,7 +116,7 @@ namespace AZ
|
||||
@autoreleasepool
|
||||
{
|
||||
AZ_PROFILE_SCOPE(RHI, "ExecuteWork");
|
||||
AZ_PROFILE_RHI_VARIABLE(m_lastExecuteDuration);
|
||||
AZ::Debug::ScopedTimer executionTimer(m_lastExecuteDuration);
|
||||
|
||||
if (request.m_signalFenceValue > 0)
|
||||
{
|
||||
@@ -128,7 +129,7 @@ namespace AZ
|
||||
}
|
||||
|
||||
{
|
||||
AZ_PROFILE_RHI_VARIABLE(m_lastPresentDuration);
|
||||
AZ::Debug::ScopedTimer presentTimer(m_lastPresentDuration);
|
||||
|
||||
for (RHI::SwapChain* swapChain : request.m_swapChainsToPresent)
|
||||
{
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
#include <AzCore/Debug/EventTrace.h>
|
||||
#include <Atom/RHI/CommandQueue.h>
|
||||
#include <Atom/RHI.Reflect/CpuTimingStatistics.h>
|
||||
#include <RHI/Device.h>
|
||||
#include <RHI/CommandQueue.h>
|
||||
#include <RHI/SwapChain.h>
|
||||
@@ -135,18 +134,23 @@ namespace AZ
|
||||
m_commandQueues[hardwareQueueIdx]->QueueGpuSignal(fence);
|
||||
}
|
||||
}
|
||||
|
||||
void CommandQueueContext::UpdateCpuTimingStatistics(RHI::CpuTimingStatistics& cpuTimingStatistics) const
|
||||
{
|
||||
cpuTimingStatistics.Reset();
|
||||
|
||||
AZStd::sys_time_t presentDuration = 0;
|
||||
for (const RHI::Ptr<CommandQueue>& commandQueue : m_commandQueues)
|
||||
void CommandQueueContext::UpdateCpuTimingStatistics() const
|
||||
{
|
||||
if (auto statsProfiler = AZ::Interface<AZ::Statistics::StatisticalProfilerProxy>::Get(); statsProfiler)
|
||||
{
|
||||
cpuTimingStatistics.m_queueStatistics.push_back({ commandQueue->GetName(), commandQueue->GetLastExecuteDuration() });
|
||||
presentDuration += commandQueue->GetLastPresentDuration();
|
||||
auto& rhiMetrics = statsProfiler->GetProfiler(rhiMetricsId);
|
||||
|
||||
AZStd::sys_time_t presentDuration = 0;
|
||||
for (const RHI::Ptr<CommandQueue>& commandQueue : m_commandQueues)
|
||||
{
|
||||
const AZ::Crc32 commandQueueId(commandQueue->GetName().GetHash());
|
||||
rhiMetrics.PushSample(commandQueueId, static_cast<double>(commandQueue->GetLastExecuteDuration()));
|
||||
presentDuration += commandQueue->GetLastPresentDuration();
|
||||
}
|
||||
|
||||
rhiMetrics.PushSample(AZ_CRC_CE("Present"), static_cast<double>(presentDuration));
|
||||
}
|
||||
cpuTimingStatistics.m_presentDuration = presentDuration;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace AZ
|
||||
/// Fences across all queues that are compiled by the frame graph compilation phase
|
||||
const FenceSet& GetCompiledFences();
|
||||
|
||||
void UpdateCpuTimingStatistics(RHI::CpuTimingStatistics& cpuTimingStatistics) const;
|
||||
void UpdateCpuTimingStatistics() const;
|
||||
private:
|
||||
AZStd::array<RHI::Ptr<CommandQueue>, RHI::HardwareQueueClassCount> m_commandQueues;
|
||||
FenceSet m_compiledFences;
|
||||
|
||||
@@ -245,9 +245,9 @@ namespace AZ
|
||||
{
|
||||
}
|
||||
|
||||
void Device::UpdateCpuTimingStatisticsInternal(RHI::CpuTimingStatistics& cpuTimingStatistics) const
|
||||
void Device::UpdateCpuTimingStatisticsInternal() const
|
||||
{
|
||||
m_commandQueueContext.UpdateCpuTimingStatistics(cpuTimingStatistics);
|
||||
m_commandQueueContext.UpdateCpuTimingStatistics();
|
||||
}
|
||||
|
||||
void Device::FillFormatsCapabilitiesInternal(FormatCapabilitiesList& formatsCapabilities)
|
||||
|
||||
@@ -161,7 +161,7 @@ namespace AZ
|
||||
RHI::ResultCode InitInternal(RHI::PhysicalDevice& physicalDevice) override;
|
||||
void ShutdownInternal() override;
|
||||
void CompileMemoryStatisticsInternal(RHI::MemoryStatisticsBuilder& builder) override;
|
||||
void UpdateCpuTimingStatisticsInternal(RHI::CpuTimingStatistics& cpuTimingStatistics) const override;
|
||||
void UpdateCpuTimingStatisticsInternal() const override;
|
||||
void BeginFrameInternal() override;
|
||||
void EndFrameInternal() override;
|
||||
void WaitForIdleInternal() override;
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace AZ
|
||||
RHI::ResultCode InitInternal([[maybe_unused]] RHI::PhysicalDevice& physicalDevice) override { return RHI::ResultCode::Success; }
|
||||
void ShutdownInternal() override {}
|
||||
void CompileMemoryStatisticsInternal([[maybe_unused]] RHI::MemoryStatisticsBuilder& builder) override {}
|
||||
void UpdateCpuTimingStatisticsInternal([[maybe_unused]] RHI::CpuTimingStatistics& cpuTimingStatistics) const override {}
|
||||
void UpdateCpuTimingStatisticsInternal() const override {}
|
||||
void BeginFrameInternal() override {}
|
||||
void EndFrameInternal() override {}
|
||||
void WaitForIdleInternal() override {}
|
||||
|
||||
@@ -5,13 +5,14 @@
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
#include <AzCore/Debug/EventTraceDrillerBus.h>
|
||||
|
||||
#include <RHI/CommandList.h>
|
||||
#include <RHI/CommandQueue.h>
|
||||
#include <RHI/Conversion.h>
|
||||
#include <RHI/Device.h>
|
||||
#include <RHI/SwapChain.h>
|
||||
#include <Atom/RHI.Reflect/CpuTimingStatistics.h>
|
||||
|
||||
#include <AzCore/Debug/Timer.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -46,7 +47,7 @@ namespace AZ
|
||||
QueueCommand([=](void* queue)
|
||||
{
|
||||
AZ_PROFILE_SCOPE(RHI, "ExecuteWork");
|
||||
AZ_PROFILE_RHI_VARIABLE(m_lastExecuteDuration);
|
||||
AZ::Debug::ScopedTimer executionTimer(m_lastExecuteDuration);
|
||||
|
||||
Queue* vulkanQueue = static_cast<Queue*>(queue);
|
||||
|
||||
@@ -80,7 +81,7 @@ namespace AZ
|
||||
}
|
||||
|
||||
{
|
||||
AZ_PROFILE_RHI_VARIABLE(m_lastPresentDuration);
|
||||
AZ::Debug::ScopedTimer presentTimer(m_lastPresentDuration);
|
||||
|
||||
// present the image of the current frame.
|
||||
for (RHI::SwapChain* swapChain : request.m_swapChainsToPresent)
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include <RHI/Semaphore.h>
|
||||
#include <RHI/Conversion.h>
|
||||
#include <RHI/SwapChain.h>
|
||||
#include <Atom/RHI.Reflect/CpuTimingStatistics.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -363,17 +362,22 @@ namespace AZ
|
||||
return queueSelection.m_familyIndex != InvalidFamilyIndex;
|
||||
}
|
||||
|
||||
void CommandQueueContext::UpdateCpuTimingStatistics(RHI::CpuTimingStatistics& cpuTimingStatistics) const
|
||||
void CommandQueueContext::UpdateCpuTimingStatistics() const
|
||||
{
|
||||
cpuTimingStatistics.Reset();
|
||||
|
||||
AZStd::sys_time_t presentDuration = 0;
|
||||
for (const RHI::Ptr<CommandQueue>& commandQueue : m_commandQueues)
|
||||
if (auto statsProfiler = AZ::Interface<AZ::Statistics::StatisticalProfilerProxy>::Get(); statsProfiler)
|
||||
{
|
||||
cpuTimingStatistics.m_queueStatistics.push_back({ commandQueue->GetName(), commandQueue->GetLastExecuteDuration() });
|
||||
presentDuration += commandQueue->GetLastPresentDuration();
|
||||
auto& rhiMetrics = statsProfiler->GetProfiler(rhiMetricsId);
|
||||
|
||||
AZStd::sys_time_t presentDuration = 0;
|
||||
for (const RHI::Ptr<CommandQueue>& commandQueue : m_commandQueues)
|
||||
{
|
||||
const AZ::Crc32 commandQueueId(commandQueue->GetName().GetHash());
|
||||
rhiMetrics.PushSample(commandQueueId, static_cast<double>(commandQueue->GetLastExecuteDuration()));
|
||||
presentDuration += commandQueue->GetLastPresentDuration();
|
||||
}
|
||||
|
||||
rhiMetrics.PushSample(AZ_CRC_CE("Present"), static_cast<double>(presentDuration));
|
||||
}
|
||||
cpuTimingStatistics.m_presentDuration = presentDuration;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,11 +16,6 @@
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace RHI
|
||||
{
|
||||
struct CpuTimingStatistics;
|
||||
}
|
||||
|
||||
namespace Vulkan
|
||||
{
|
||||
class Device;
|
||||
@@ -62,7 +57,7 @@ namespace AZ
|
||||
AZStd::vector<uint32_t> GetQueueFamilyIndices(const RHI::HardwareQueueClassMask hardwareQueueClassMask) const;
|
||||
VkPipelineStageFlags GetSupportedPipelineStages(uint32_t queueFamilyIndex) const;
|
||||
|
||||
void UpdateCpuTimingStatistics(RHI::CpuTimingStatistics& cpuTimingStatistics) const;
|
||||
void UpdateCpuTimingStatistics() const;
|
||||
|
||||
private:
|
||||
Descriptor m_descriptor;
|
||||
|
||||
@@ -547,9 +547,9 @@ namespace AZ
|
||||
physicalDevice.CompileMemoryStatistics(builder);
|
||||
}
|
||||
|
||||
void Device::UpdateCpuTimingStatisticsInternal(RHI::CpuTimingStatistics& cpuTimingStatistics) const
|
||||
void Device::UpdateCpuTimingStatisticsInternal() const
|
||||
{
|
||||
m_commandQueueContext.UpdateCpuTimingStatistics(cpuTimingStatistics);
|
||||
m_commandQueueContext.UpdateCpuTimingStatistics();
|
||||
}
|
||||
|
||||
AZStd::vector<RHI::Format> Device::GetValidSwapChainImageFormats(const RHI::WindowHandle& windowHandle) const
|
||||
|
||||
@@ -126,7 +126,7 @@ namespace AZ
|
||||
void EndFrameInternal() override;
|
||||
void WaitForIdleInternal() override;
|
||||
void CompileMemoryStatisticsInternal(RHI::MemoryStatisticsBuilder& builder) override;
|
||||
void UpdateCpuTimingStatisticsInternal(RHI::CpuTimingStatistics& cpuTimingStatistics) const override;
|
||||
void UpdateCpuTimingStatisticsInternal() const override;
|
||||
AZStd::vector<RHI::Format> GetValidSwapChainImageFormats(const RHI::WindowHandle& windowHandle) const override;
|
||||
AZStd::chrono::microseconds GpuTimestampToMicroseconds(uint64_t gpuTimestamp, RHI::HardwareQueueClass queueClass) const override;
|
||||
void FillFormatsCapabilitiesInternal(FormatCapabilitiesList& formatsCapabilities) override;
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace UnitTest
|
||||
void EndFrameInternal() override {}
|
||||
void WaitForIdleInternal() override {}
|
||||
void CompileMemoryStatisticsInternal(AZ::RHI::MemoryStatisticsBuilder&) override {}
|
||||
void UpdateCpuTimingStatisticsInternal([[maybe_unused]] AZ::RHI::CpuTimingStatistics& cpuTimingStatistics) const override {}
|
||||
void UpdateCpuTimingStatisticsInternal() const override {}
|
||||
AZStd::chrono::microseconds GpuTimestampToMicroseconds([[maybe_unused]] uint64_t gpuTimestamp, [[maybe_unused]] AZ::RHI::HardwareQueueClass queueClass) const override
|
||||
{
|
||||
return AZStd::chrono::microseconds();
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
#include <Atom/RHI/RHISystemInterface.h>
|
||||
#include <Atom/RHI.Reflect/CpuTimingStatistics.h>
|
||||
#include <Atom/RHI/CpuProfiler.h>
|
||||
#include <Atom/RPI.Public/Pass/ParentPass.h>
|
||||
#include <Atom/RPI.Public/Pass/PassSystemInterface.h>
|
||||
@@ -96,10 +95,10 @@ namespace MaterialEditor
|
||||
ResetStats();
|
||||
}
|
||||
|
||||
const AZ::RHI::CpuTimingStatistics* stats = AZ::RHI::RHISystemInterface::Get()->GetCpuTimingStatistics();
|
||||
if (stats)
|
||||
double frameTime = AZ::RHI::RHISystemInterface::Get()->GetCpuFrameTime();
|
||||
if (frameTime > 0)
|
||||
{
|
||||
m_cpuFrameTimeMs.PushSample(stats->GetFrameToFrameTimeMilliseconds());
|
||||
m_cpuFrameTimeMs.PushSample(frameTime);
|
||||
}
|
||||
|
||||
AZ::RHI::Ptr<AZ::RPI::ParentPass> rootPass = AZ::RPI::PassSystemInterface::Get()->GetRootPass();
|
||||
|
||||
@@ -12,17 +12,11 @@
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/Math/Random.h>
|
||||
|
||||
#include <Atom/RHI.Reflect/CpuTimingStatistics.h>
|
||||
#include <Atom/RHI/CpuProfiler.h>
|
||||
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace RHI
|
||||
{
|
||||
struct CpuTimingStatistics;
|
||||
}
|
||||
|
||||
namespace Render
|
||||
{
|
||||
//! Stores all the data associated with a row in the table.
|
||||
@@ -88,11 +82,17 @@ namespace AZ
|
||||
using GroupRegionName = AZ::RHI::CachedTimeRegion::GroupRegionName;
|
||||
|
||||
public:
|
||||
struct CpuTimingEntry
|
||||
{
|
||||
const AZStd::string& m_name;
|
||||
double m_executeDuration;
|
||||
};
|
||||
|
||||
ImGuiCpuProfiler() = default;
|
||||
~ImGuiCpuProfiler() = default;
|
||||
|
||||
//! Draws the overall CPU profiling window, defaults to the statistical view
|
||||
void Draw(bool& keepDrawing, const AZ::RHI::CpuTimingStatistics& cpuTimingStatistics);
|
||||
void Draw(bool& keepDrawing);
|
||||
|
||||
private:
|
||||
static constexpr float RowHeight = 35.0;
|
||||
@@ -121,11 +121,14 @@ namespace AZ
|
||||
// Sort the table by a given column, rearranges the pointers in m_tableData.
|
||||
void SortTable(ImGuiTableSortSpecs* sortSpecs);
|
||||
|
||||
// gather the latest timing statistics
|
||||
void CacheCpuTimingStatistics();
|
||||
|
||||
// Get the profiling data from the last frame, only called when the profiler is not paused.
|
||||
void CollectFrameData();
|
||||
|
||||
// Cull old data from internal storage, only called when profiler is not paused.
|
||||
void CullFrameData(const AZ::RHI::CpuTimingStatistics& currentCpuTimingStatistics);
|
||||
void CullFrameData();
|
||||
|
||||
// Draws a single block onto the timeline into the specified row
|
||||
void DrawBlock(const TimeRegion& block, u64 targetRow);
|
||||
@@ -204,7 +207,8 @@ namespace AZ
|
||||
bool m_enableVisualizer = false;
|
||||
|
||||
// Last captured CPU timing statistics
|
||||
AZ::RHI::CpuTimingStatistics m_cpuTimingStatisticsWhenPause;
|
||||
AZStd::vector<CpuTimingEntry> m_cpuTimingStatisticsWhenPause;
|
||||
AZStd::sys_time_t m_frameToFrameTime{};
|
||||
|
||||
AZStd::string m_lastCapturedFilePath;
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
*/
|
||||
|
||||
#include <Atom/Feature/Utils/ProfilingCaptureBus.h>
|
||||
#include <Atom/RHI.Reflect/CpuTimingStatistics.h>
|
||||
#include <Atom/RHI/CpuProfiler.h>
|
||||
#include <Atom/RHI/CpuProfilerImpl.h>
|
||||
#include <Atom/RPI.Edit/Common/JsonUtils.h>
|
||||
@@ -16,6 +15,7 @@
|
||||
#include <AzCore/Casting/lossy_cast.h>
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <AzCore/JSON/filereadstream.h>
|
||||
#include <AzCore/Statistics/StatisticalProfilerProxy.h>
|
||||
#include <AzCore/Serialization/Json/JsonSerialization.h>
|
||||
#include <AzCore/Serialization/Json/JsonSerializationResult.h>
|
||||
#include <AzCore/std/containers/map.h>
|
||||
@@ -31,7 +31,7 @@ namespace AZ
|
||||
{
|
||||
namespace CpuProfilerImGuiHelper
|
||||
{
|
||||
inline float TicksToMs(AZStd::sys_time_t ticks)
|
||||
inline float TicksToMs(double ticks)
|
||||
{
|
||||
// Note: converting to microseconds integer before converting to milliseconds float
|
||||
const AZStd::sys_time_t ticksPerSecond = AZStd::GetTimeTicksPerSecond();
|
||||
@@ -39,6 +39,11 @@ namespace AZ
|
||||
return static_cast<float>((ticks * 1000) / (ticksPerSecond / 1000)) / 1000.0f;
|
||||
}
|
||||
|
||||
inline float TicksToMs(AZStd::sys_time_t ticks)
|
||||
{
|
||||
return TicksToMs(static_cast<double>(ticks));
|
||||
}
|
||||
|
||||
using DeserializedCpuData = AZStd::vector<RHI::CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializerEntry>;
|
||||
inline Outcome<DeserializedCpuData, AZStd::string> LoadSavedCpuProfilingStatistics(const AZStd::string& capturePath)
|
||||
{
|
||||
@@ -108,7 +113,9 @@ namespace AZ
|
||||
}
|
||||
} // namespace CpuProfilerImGuiHelper
|
||||
|
||||
inline void ImGuiCpuProfiler::Draw(bool& keepDrawing, const AZ::RHI::CpuTimingStatistics& currentCpuTimingStatistics)
|
||||
|
||||
|
||||
inline void ImGuiCpuProfiler::Draw(bool& keepDrawing)
|
||||
{
|
||||
// Cache the value to detect if it was changed by ImGui(user pressed 'x')
|
||||
const bool cachedShowCpuProfiler = keepDrawing;
|
||||
@@ -121,10 +128,10 @@ namespace AZ
|
||||
if (!m_paused)
|
||||
{
|
||||
// Update region map and cache the input cpu timing statistics when the profiling is not paused
|
||||
m_cpuTimingStatisticsWhenPause = currentCpuTimingStatistics;
|
||||
CacheCpuTimingStatistics();
|
||||
|
||||
CollectFrameData();
|
||||
CullFrameData(currentCpuTimingStatistics);
|
||||
CullFrameData();
|
||||
|
||||
// Only listen to system ticks when the profiler is active
|
||||
if (!SystemTickBus::Handler::BusIsConnected())
|
||||
@@ -354,19 +361,12 @@ namespace AZ
|
||||
{
|
||||
DrawCommonHeader();
|
||||
|
||||
const AZ::RHI::CpuTimingStatistics& cpuTimingStatistics = m_cpuTimingStatisticsWhenPause;
|
||||
|
||||
const auto ShowTimeInMs = [](AZStd::sys_time_t duration)
|
||||
{
|
||||
ImGui::Text("%.2f ms", CpuProfilerImGuiHelper::TicksToMs(duration));
|
||||
};
|
||||
|
||||
const auto ShowRow = [&ShowTimeInMs](const char* regionLabel, AZStd::sys_time_t duration)
|
||||
const auto ShowRow = [](const char* regionLabel, double duration)
|
||||
{
|
||||
ImGui::Text("%s", regionLabel);
|
||||
ImGui::NextColumn();
|
||||
|
||||
ShowTimeInMs(duration);
|
||||
ImGui::Text("%.2f ms", CpuProfilerImGuiHelper::TicksToMs(duration));
|
||||
ImGui::NextColumn();
|
||||
};
|
||||
|
||||
@@ -377,11 +377,9 @@ namespace AZ
|
||||
ImGui::SetColumnWidth(0, 660.0f);
|
||||
ImGui::SetColumnWidth(1, 100.0f);
|
||||
|
||||
ShowRow("Frame to Frame Time", cpuTimingStatistics.m_frameToFrameTime);
|
||||
ShowRow("Present Time", cpuTimingStatistics.m_presentDuration);
|
||||
for (const auto& queueStatistics : cpuTimingStatistics.m_queueStatistics)
|
||||
for (const auto& queueStatistics : m_cpuTimingStatisticsWhenPause)
|
||||
{
|
||||
ShowRow(queueStatistics.m_queueName.GetCStr(), queueStatistics.m_executeDuration);
|
||||
ShowRow(queueStatistics.m_name.c_str(), queueStatistics.m_executeDuration);
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
@@ -653,6 +651,32 @@ namespace AZ
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
inline void ImGuiCpuProfiler::CacheCpuTimingStatistics()
|
||||
{
|
||||
using namespace AZ::Statistics;
|
||||
|
||||
m_cpuTimingStatisticsWhenPause.clear();
|
||||
if (auto statsProfiler = AZ::Interface<StatisticalProfilerProxy>::Get(); statsProfiler)
|
||||
{
|
||||
auto& rhiMetrics = statsProfiler->GetProfiler(AZ_CRC_CE("RHI"));
|
||||
|
||||
const NamedRunningStatistic* frameTimeMetric = rhiMetrics.GetStatistic(AZ_CRC_CE("Frame to Frame Time"));
|
||||
if (frameTimeMetric)
|
||||
{
|
||||
m_frameToFrameTime = static_cast<AZStd::sys_time_t>(frameTimeMetric->GetMostRecentSample());
|
||||
}
|
||||
|
||||
AZStd::vector<NamedRunningStatistic*> statistics;
|
||||
rhiMetrics.GetStatsManager().GetAllStatistics(statistics);
|
||||
|
||||
for (NamedRunningStatistic* stat : statistics)
|
||||
{
|
||||
m_cpuTimingStatisticsWhenPause.push_back({ stat->GetName(), stat->GetMostRecentSample() });
|
||||
stat->Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void ImGuiCpuProfiler::CollectFrameData()
|
||||
{
|
||||
// We maintain separate datastores for the visualizer and the statistical view because they require different
|
||||
@@ -721,10 +745,9 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
inline void ImGuiCpuProfiler::CullFrameData(const AZ::RHI::CpuTimingStatistics& currentCpuTimingStatistics)
|
||||
inline void ImGuiCpuProfiler::CullFrameData()
|
||||
{
|
||||
const AZStd::sys_time_t frameToFrameTime = currentCpuTimingStatistics.m_frameToFrameTime;
|
||||
const AZStd::sys_time_t deleteBeforeTick = AZStd::GetTimeNowTicks() - frameToFrameTime * m_framesToCollect;
|
||||
const AZStd::sys_time_t deleteBeforeTick = AZStd::GetTimeNowTicks() - m_frameToFrameTime * m_framesToCollect;
|
||||
|
||||
// Remove old frame boundary data
|
||||
auto firstBoundaryToKeepItr = AZStd::upper_bound(m_frameEndTicks.begin(), m_frameEndTicks.end(), deleteBeforeTick);
|
||||
|
||||
@@ -86,11 +86,7 @@ namespace AtomImGuiTools
|
||||
}
|
||||
if (m_showCpuProfiler)
|
||||
{
|
||||
const AZ::RHI::CpuTimingStatistics* stats = AZ::RHI::RHISystemInterface::Get()->GetCpuTimingStatistics();
|
||||
if (stats)
|
||||
{
|
||||
m_imguiCpuProfiler.Draw(m_showCpuProfiler, *stats);
|
||||
}
|
||||
m_imguiCpuProfiler.Draw(m_showCpuProfiler);
|
||||
}
|
||||
if (m_showTransientAttachmentProfiler)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user