Atom Tools: Moved performance monitor system component from ME to ATF

Moved the performance monitor system component and metrics gathering from the material editor into atom tools framework so it can be reused and extended by other applications.
Replaced the custom performance monitor docked window in the material editor with status bar widgets that are always visible and take up no screen real estate. This could possibly be moved to the base application class or rendered on top of the viewport.

Signed-off-by: Guthrie Adams <guthadam@amazon.com>
This commit is contained in:
Guthrie Adams
2022-01-24 22:17:01 -06:00
parent e1cb40fa33
commit 191db77e4d
14 changed files with 136 additions and 330 deletions
@@ -8,16 +8,16 @@
#include <Viewport/MaterialViewportComponent.h>
#include <Viewport/MaterialViewportModule.h>
#include <Viewport/PerformanceMonitorComponent.h>
namespace MaterialEditor
{
MaterialViewportModule::MaterialViewportModule()
{
// Push results of [MyComponent]::CreateDescriptor() into m_descriptors here.
m_descriptors.insert(m_descriptors.end(), {
MaterialViewportComponent::CreateDescriptor(),
PerformanceMonitorComponent::CreateDescriptor(),
m_descriptors.insert(
m_descriptors.end(),
{
MaterialViewportComponent::CreateDescriptor(),
});
}
@@ -25,7 +25,6 @@ namespace MaterialEditor
{
return AZ::ComponentTypeList{
azrtti_typeid<MaterialViewportComponent>(),
azrtti_typeid<PerformanceMonitorComponent>(),
};
}
}
} // namespace MaterialEditor
@@ -50,7 +50,6 @@
#include <Viewport/MaterialViewportRequestBus.h>
#include <Viewport/MaterialViewportSettings.h>
#include <Viewport/MaterialViewportWidget.h>
#include <Viewport/PerformanceMonitorRequestBus.h>
#include <Viewport/ui_MaterialViewportWidget.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
@@ -462,8 +461,6 @@ namespace MaterialEditor
m_renderPipeline->AddToRenderTickOnce();
PerformanceMonitorRequestBus::Broadcast(&PerformanceMonitorRequestBus::Handler::GatherMetrics);
if (m_shadowCatcherMaterial)
{
// Compile the m_shadowCatcherMaterial in OnTick because changes can only be compiled once per frame.
@@ -1,25 +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/Memory/Memory.h>
#include <AzCore/RTTI/RTTI.h>
#include <AzCore/RTTI/ReflectContext.h>
#include <AzCore/Serialization/SerializeContext.h>
namespace MaterialEditor
{
//! Data structure containing performance metrics for Material Editor
struct PerformanceMetrics final
{
AZ_CLASS_ALLOCATOR(PerformanceMetrics, AZ::SystemAllocator, 0);
double m_cpuFrameTimeMs = 0;
double m_gpuFrameTimeMs = 0;
};
} // namespace MaterialEditor
@@ -1,123 +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
*
*/
#include <AzCore/Serialization/SerializeContext.h>
#include <Atom/RHI/RHISystemInterface.h>
#include <Atom/RPI.Public/Pass/ParentPass.h>
#include <Atom/RPI.Public/Pass/PassSystemInterface.h>
#include <Viewport/PerformanceMonitorComponent.h>
namespace MaterialEditor
{
void PerformanceMonitorComponent::Reflect(AZ::ReflectContext* context)
{
if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
{
serialize->Class<PerformanceMonitorComponent, AZ::Component>()
->Version(0);
}
}
PerformanceMonitorComponent::PerformanceMonitorComponent()
{
}
void PerformanceMonitorComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
{
provided.push_back(AZ_CRC_CE("PerformanceMonitorService"));
}
void PerformanceMonitorComponent::Init()
{
}
void PerformanceMonitorComponent::Activate()
{
PerformanceMonitorRequestBus::Handler::BusConnect();
}
void PerformanceMonitorComponent::Deactivate()
{
PerformanceMonitorRequestBus::Handler::BusDisconnect();
}
void PerformanceMonitorComponent::SetProfilerEnabled(bool enabled)
{
if (m_profilingEnabled == enabled)
{
return;
}
AZ::RHI::Ptr<AZ::RPI::ParentPass> rootPass = AZ::RPI::PassSystemInterface::Get()->GetRootPass();
if (rootPass)
{
rootPass->SetTimestampQueryEnabled(enabled);
}
else
{
AZ_Error("PerformanceMonitorComponent", false, "Failed to find root pass.");
}
if (enabled)
{
ResetStats();
}
m_profilingEnabled = enabled;
}
void PerformanceMonitorComponent::GatherMetrics()
{
if (!m_profilingEnabled)
{
return;
}
if (++m_sample > SampleCount)
{
m_sample = 0;
UpdateMetrics();
ResetStats();
}
double frameTime = AZ::RHI::RHISystemInterface::Get()->GetCpuFrameTime();
if (frameTime > 0)
{
m_cpuFrameTimeMs.PushSample(frameTime);
}
AZ::RHI::Ptr<AZ::RPI::ParentPass> rootPass = AZ::RPI::PassSystemInterface::Get()->GetRootPass();
if (rootPass)
{
AZ::RPI::TimestampResult timestampResult = rootPass->GetLatestTimestampResult();
double gpuFrameTimeMs = aznumeric_cast<double>(timestampResult.GetDurationInNanoseconds()) / 1000000;
m_gpuFrameTimeMs.PushSample(gpuFrameTimeMs);
}
}
const PerformanceMetrics& PerformanceMonitorComponent::GetMetrics()
{
UpdateMetrics();
return m_metrics;
}
void PerformanceMonitorComponent::UpdateMetrics()
{
m_metrics.m_cpuFrameTimeMs = m_cpuFrameTimeMs.GetAverage();
m_metrics.m_gpuFrameTimeMs = m_gpuFrameTimeMs.GetAverage();
}
void PerformanceMonitorComponent::ResetStats()
{
m_cpuFrameTimeMs.Reset();
m_gpuFrameTimeMs.Reset();
}
}
@@ -1,58 +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/RPI.Public/Pass/Pass.h>
#include <AzCore/Component/Component.h>
#include <AzCore/Statistics/RunningStatistic.h>
#include <Viewport/PerformanceMonitorRequestBus.h>
namespace MaterialEditor
{
//! PerformanceMonitorComponent monitors performance within Material Editor
class PerformanceMonitorComponent
: public AZ::Component
, private PerformanceMonitorRequestBus::Handler
{
public:
AZ_COMPONENT(PerformanceMonitorComponent, "{C2F54D1B-A106-4922-82BE-ACB7A168D4AF}");
static void Reflect(AZ::ReflectContext* context);
PerformanceMonitorComponent();
~PerformanceMonitorComponent() = default;
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
private:
// AZ::Component overrides...
void Init() override;
void Activate() override;
void Deactivate() override;
// PerformanceMonitorRequestBus::Handler interface overrides...
void SetProfilerEnabled(bool enabled) override;
void GatherMetrics() override;
const PerformanceMetrics& GetMetrics() override;
void UpdateMetrics();
void ResetStats();
bool m_profilingEnabled = false;
AZ::Statistics::RunningStatistic m_cpuFrameTimeMs;
AZ::Statistics::RunningStatistic m_gpuFrameTimeMs;
PerformanceMetrics m_metrics;
// Number of samples to average for each metric
static constexpr int SampleCount = 10;
int m_sample = 0;
};
}
@@ -1,33 +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 <Viewport/PerformanceMetrics.h>
namespace MaterialEditor
{
//! Provides communication with Performance Monitor
class PerformanceMonitorRequests
: public AZ::EBusTraits
{
public:
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
//! Enable or disable CPU and GPU monitoring
//! @param enabled whether performance monitoring should be enabled
virtual void SetProfilerEnabled(bool enabled) = 0;
//! Gather performance metrics for the current frame
virtual void GatherMetrics() = 0;
//! Get current metrics
virtual const PerformanceMetrics& GetMetrics() = 0;
};
using PerformanceMonitorRequestBus = AZ::EBus<PerformanceMonitorRequests>;
} // namespace MaterialEditor
@@ -10,6 +10,7 @@
#include <Atom/RPI.Edit/Material/MaterialSourceData.h>
#include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
#include <AtomToolsFramework/PerformanceMonitor/PerformanceMonitorRequestBus.h>
#include <AtomToolsFramework/Util/Util.h>
#include <AzQtComponents/Components/StyleManager.h>
#include <AzQtComponents/Components/WindowDecorationWrapper.h>
@@ -19,7 +20,6 @@
#include <Window/MaterialEditorWindow.h>
#include <Window/MaterialEditorWindowSettings.h>
#include <Window/MaterialInspector/MaterialInspector.h>
#include <Window/PerformanceMonitor/PerformanceMonitorWidget.h>
#include <Window/SettingsDialog/SettingsDialog.h>
#include <Window/ViewportSettingsInspector/ViewportSettingsInspector.h>
@@ -30,6 +30,7 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnin
#include <QDesktopServices>
#include <QFileDialog>
#include <QMessageBox>
#include <QStatusBar>
#include <QUrl>
#include <QWindow>
AZ_POP_DISABLE_WARNING
@@ -95,10 +96,7 @@ namespace MaterialEditor
AddDockWidget("Inspector", new MaterialInspector, Qt::RightDockWidgetArea, Qt::Vertical);
AddDockWidget("Viewport Settings", new ViewportSettingsInspector, Qt::LeftDockWidgetArea, Qt::Vertical);
AddDockWidget("Performance Monitor", new PerformanceMonitorWidget, Qt::BottomDockWidgetArea, Qt::Horizontal);
SetDockWidgetVisible("Viewport Settings", false);
SetDockWidgetVisible("Performance Monitor", false);
// Restore geometry and show the window
mainWindowWrapper->showFromSettings();
@@ -114,6 +112,14 @@ namespace MaterialEditor
}
OnDocumentOpened(AZ::Uuid::CreateNull());
SetupMetrics();
}
MaterialEditorWindow::~MaterialEditorWindow()
{
AtomToolsFramework::PerformanceMonitorRequestBus::Broadcast(
&AtomToolsFramework::PerformanceMonitorRequestBus::Handler::SetProfilerEnabled, false);
}
void MaterialEditorWindow::ResizeViewportRenderTarget(uint32_t width, uint32_t height)
@@ -207,6 +213,38 @@ namespace MaterialEditor
Base::closeEvent(closeEvent);
}
void MaterialEditorWindow::SetupMetrics()
{
m_statusBarCpuTime = new QLabel(this);
statusBar()->addPermanentWidget(m_statusBarCpuTime);
m_statusBarGpuTime = new QLabel(this);
statusBar()->addPermanentWidget(m_statusBarGpuTime);
m_statusBarFps = new QLabel(this);
statusBar()->addPermanentWidget(m_statusBarFps);
static constexpr int UpdateIntervalMs = 1000;
m_metricsTimer.setInterval(UpdateIntervalMs);
m_metricsTimer.start();
connect(&m_metricsTimer, &QTimer::timeout, this, &MaterialEditorWindow::UpdateMetrics);
AtomToolsFramework::PerformanceMonitorRequestBus::Broadcast(
&AtomToolsFramework::PerformanceMonitorRequestBus::Handler::SetProfilerEnabled, true);
UpdateMetrics();
}
void MaterialEditorWindow::UpdateMetrics()
{
AtomToolsFramework::PerformanceMetrics metrics = {};
AtomToolsFramework::PerformanceMonitorRequestBus::BroadcastResult(
metrics, &AtomToolsFramework::PerformanceMonitorRequestBus::Handler::GetMetrics);
m_statusBarCpuTime->setText(tr("CPU Time %1 ms").arg(QString::number(metrics.m_cpuFrameTimeMs, 'f', 2)));
m_statusBarGpuTime->setText(tr("GPU Time %1 ms").arg(QString::number(metrics.m_gpuFrameTimeMs, 'f', 2)));
int frameRate = metrics.m_cpuFrameTimeMs > 0 ? aznumeric_cast<int>(1000 / metrics.m_cpuFrameTimeMs) : 0;
m_statusBarFps->setText(tr("FPS %1").arg(QString::number(frameRate)));
}
} // namespace MaterialEditor
#include <Window/moc_MaterialEditorWindow.cpp>
@@ -14,6 +14,7 @@
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <Viewport/MaterialViewportWidget.h>
#include <Window/ToolBar/MaterialEditorToolBar.h>
#include <QTimer>
AZ_POP_DISABLE_WARNING
#endif
@@ -33,7 +34,7 @@ namespace MaterialEditor
using Base = AtomToolsFramework::AtomToolsDocumentMainWindow;
MaterialEditorWindow(QWidget* parent = 0);
~MaterialEditorWindow() = default;
~MaterialEditorWindow();
protected:
void ResizeViewportRenderTarget(uint32_t width, uint32_t height) override;
@@ -48,7 +49,14 @@ namespace MaterialEditor
void closeEvent(QCloseEvent* closeEvent) override;
void SetupMetrics();
void UpdateMetrics();
MaterialViewportWidget* m_materialViewport = {};
MaterialEditorToolBar* m_toolBar = {};
QLabel* m_statusBarFps = {};
QLabel* m_statusBarCpuTime = {};
QLabel* m_statusBarGpuTime = {};
QTimer m_metricsTimer;
};
} // namespace MaterialEditor
@@ -1,57 +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
*
*/
#include <Viewport/PerformanceMonitorRequestBus.h>
#include <Window/PerformanceMonitor/PerformanceMonitorWidget.h>
#include <Window/PerformanceMonitor/ui_PerformanceMonitorWidget.h>
#include <QTimer>
namespace MaterialEditor
{
PerformanceMonitorWidget::PerformanceMonitorWidget(QWidget* parent)
: QWidget(parent)
, m_ui(new Ui::PerformanceMonitorWidget)
{
m_ui->setupUi(this);
m_updateTimer.setInterval(UpdateIntervalMs);
connect(&m_updateTimer, &QTimer::timeout, this, &PerformanceMonitorWidget::UpdateMetrics);
}
PerformanceMonitorWidget::~PerformanceMonitorWidget() = default;
void PerformanceMonitorWidget::showEvent(QShowEvent* event)
{
QWidget::showEvent(event);
m_updateTimer.start();
PerformanceMonitorRequestBus::Broadcast(&PerformanceMonitorRequestBus::Handler::SetProfilerEnabled, true);
}
void PerformanceMonitorWidget::hideEvent(QHideEvent* event)
{
QWidget::hideEvent(event);
m_updateTimer.stop();
PerformanceMonitorRequestBus::Broadcast(&PerformanceMonitorRequestBus::Handler::SetProfilerEnabled, false);
}
void PerformanceMonitorWidget::UpdateMetrics()
{
PerformanceMetrics metrics;
PerformanceMonitorRequestBus::BroadcastResult(metrics, &PerformanceMonitorRequestBus::Handler::GetMetrics);
m_ui->m_cpuFrameTimeValue->setText(QString("%1 ms").arg(QString::number(metrics.m_cpuFrameTimeMs, 'f', 2)));
m_ui->m_gpuFrameTimeValue->setText(QString("%1 ms").arg(QString::number(metrics.m_gpuFrameTimeMs, 'f', 2)));
int frameRate = metrics.m_cpuFrameTimeMs > 0 ? aznumeric_cast<int>(1000 / metrics.m_cpuFrameTimeMs) : 0;
m_ui->m_frameRateValue->setText(QString::number(frameRate));
}
} // namespace MaterialEditor
#include <Window/PerformanceMonitor/moc_PerformanceMonitorWidget.cpp>
@@ -1,44 +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 <QWidget>
#include <QTimer>
namespace Ui
{
class PerformanceMonitorWidget;
}
namespace MaterialEditor
{
//! Displays performance metrics for Material Editor
class PerformanceMonitorWidget
: public QWidget
{
Q_OBJECT
public:
PerformanceMonitorWidget(QWidget* parent = nullptr);
~PerformanceMonitorWidget();
private slots:
void UpdateMetrics();
private:
void showEvent(QShowEvent* event) override;
void hideEvent(QHideEvent* event) override;
QScopedPointer<Ui::PerformanceMonitorWidget> m_ui;
QTimer m_updateTimer;
//! interval to request performance metrics
static constexpr int UpdateIntervalMs = 1000;
};
} // namespace MaterialEditor
@@ -1,133 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PerformanceMonitorWidget</class>
<widget class="QWidget" name="PerformanceMonitorWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>237</width>
<height>200</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>200</height>
</size>
</property>
<property name="windowTitle">
<string>Performance Monitor</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="m_frameRateLayout">
<item>
<widget class="QLabel" name="m_frameRateTitle">
<property name="text">
<string>Frame Rate:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="m_frameRateValue">
<property name="text">
<string>0</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="m_cpuFrameTimeLayout">
<item>
<widget class="QLabel" name="m_cpuFrameTimeTitle">
<property name="text">
<string>CPU Frame Time:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="m_cpuFrameTimeValue">
<property name="text">
<string>0</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="m_gpuFrameTimeLayout">
<item>
<widget class="QLabel" name="m_gpuFrameTimeTitle">
<property name="text">
<string>GPU Frame Time:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="m_gpuFrameTimeValue">
<property name="text">
<string>0</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>67</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
@@ -23,8 +23,6 @@ set(FILES
Source/Viewport/MaterialViewportSettings.h
Source/Viewport/MaterialViewportRequestBus.h
Source/Viewport/MaterialViewportNotificationBus.h
Source/Viewport/PerformanceMetrics.h
Source/Viewport/PerformanceMonitorRequestBus.h
Source/Viewport/InputController/MaterialEditorViewportInputController.cpp
Source/Viewport/InputController/MaterialEditorViewportInputController.h
Source/Viewport/InputController/Behavior.cpp
@@ -49,8 +47,6 @@ set(FILES
Source/Viewport/MaterialViewportWidget.cpp
Source/Viewport/MaterialViewportWidget.h
Source/Viewport/MaterialViewportWidget.ui
Source/Viewport/PerformanceMonitorComponent.cpp
Source/Viewport/PerformanceMonitorComponent.h
Source/Window/MaterialEditorWindowSettings.h
Source/Window/MaterialEditorBrowserInteractions.h
@@ -67,9 +63,6 @@ set(FILES
Source/Window/CreateMaterialDialog/CreateMaterialDialog.cpp
Source/Window/CreateMaterialDialog/CreateMaterialDialog.h
Source/Window/CreateMaterialDialog/CreateMaterialDialog.ui
Source/Window/PerformanceMonitor/PerformanceMonitorWidget.cpp
Source/Window/PerformanceMonitor/PerformanceMonitorWidget.h
Source/Window/PerformanceMonitor/PerformanceMonitorWidget.ui
Source/Window/ToolBar/MaterialEditorToolBar.h
Source/Window/ToolBar/MaterialEditorToolBar.cpp
Source/Window/ToolBar/ModelPresetComboBox.h