aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/citra_qt
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner <yuriks@yuriks.net>2015-02-05 14:53:25 -0200
committerGravatar Yuri Kunde Schlesner <yuriks@yuriks.net>2015-03-01 21:47:13 -0300
commitcd1fbfcf1b70e365d81480ec0f56db19ed02454f (patch)
treeb220b105d1b8016bb258047683bf2d03795c8881 /src/citra_qt
parentc1d29ac20240ad92a49b84409b92ed1d326720a9 (diff)
Add profiling infrastructure and widget
Diffstat (limited to 'src/citra_qt')
-rw-r--r--src/citra_qt/CMakeLists.txt3
-rw-r--r--src/citra_qt/debugger/profiler.cpp138
-rw-r--r--src/citra_qt/debugger/profiler.h50
-rw-r--r--src/citra_qt/debugger/profiler.ui33
-rw-r--r--src/citra_qt/main.cpp6
-rw-r--r--src/citra_qt/main.h2
6 files changed, 232 insertions, 0 deletions
diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt
index 586bc84b..a1ad00f5 100644
--- a/src/citra_qt/CMakeLists.txt
+++ b/src/citra_qt/CMakeLists.txt
@@ -13,6 +13,7 @@ set(SRCS
debugger/graphics_cmdlists.cpp
debugger/graphics_framebuffer.cpp
debugger/graphics_vertex_shader.cpp
+ debugger/profiler.cpp
debugger/ramview.cpp
debugger/registers.cpp
util/spinbox.cpp
@@ -35,6 +36,7 @@ set(HEADERS
debugger/graphics_cmdlists.h
debugger/graphics_framebuffer.h
debugger/graphics_vertex_shader.h
+ debugger/profiler.h
debugger/ramview.h
debugger/registers.h
util/spinbox.h
@@ -48,6 +50,7 @@ set(UIS
config/controller_config.ui
debugger/callstack.ui
debugger/disassembler.ui
+ debugger/profiler.ui
debugger/registers.ui
hotkeys.ui
main.ui
diff --git a/src/citra_qt/debugger/profiler.cpp b/src/citra_qt/debugger/profiler.cpp
new file mode 100644
index 00000000..ae0568b6
--- /dev/null
+++ b/src/citra_qt/debugger/profiler.cpp
@@ -0,0 +1,138 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "profiler.h"
+
+#include "common/profiler_reporting.h"
+
+using namespace Common::Profiling;
+
+static QVariant GetDataForColumn(int col, const AggregatedDuration& duration)
+{
+ static auto duration_to_float = [](Duration dur) -> float {
+ using FloatMs = std::chrono::duration<float, std::chrono::milliseconds::period>;
+ return std::chrono::duration_cast<FloatMs>(dur).count();
+ };
+
+ switch (col) {
+ case 1: return duration_to_float(duration.avg);
+ case 2: return duration_to_float(duration.min);
+ case 3: return duration_to_float(duration.max);
+ default: return QVariant();
+ }
+}
+
+static const TimingCategoryInfo* GetCategoryInfo(int id)
+{
+ const auto& categories = GetProfilingManager().GetTimingCategoriesInfo();
+ if (id >= categories.size()) {
+ return nullptr;
+ } else {
+ return &categories[id];
+ }
+}
+
+ProfilerModel::ProfilerModel(QObject* parent) : QAbstractItemModel(parent)
+{
+ updateProfilingInfo();
+ const auto& categories = GetProfilingManager().GetTimingCategoriesInfo();
+ results.time_per_category.resize(categories.size());
+}
+
+QVariant ProfilerModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
+ switch (section) {
+ case 0: return tr("Category");
+ case 1: return tr("Avg");
+ case 2: return tr("Min");
+ case 3: return tr("Max");
+ }
+ }
+
+ return QVariant();
+}
+
+QModelIndex ProfilerModel::index(int row, int column, const QModelIndex& parent) const
+{
+ return createIndex(row, column);
+}
+
+QModelIndex ProfilerModel::parent(const QModelIndex& child) const
+{
+ return QModelIndex();
+}
+
+int ProfilerModel::columnCount(const QModelIndex& parent) const
+{
+ return 4;
+}
+
+int ProfilerModel::rowCount(const QModelIndex& parent) const
+{
+ if (parent.isValid()) {
+ return 0;
+ } else {
+ return results.time_per_category.size() + 2;
+ }
+}
+
+QVariant ProfilerModel::data(const QModelIndex& index, int role) const
+{
+ if (role == Qt::DisplayRole) {
+ if (index.row() == 0) {
+ if (index.column() == 0) {
+ return tr("Frame");
+ } else {
+ return GetDataForColumn(index.column(), results.frame_time);
+ }
+ } else if (index.row() == 1) {
+ if (index.column() == 0) {
+ return tr("Frame (with swapping)");
+ } else {
+ return GetDataForColumn(index.column(), results.interframe_time);
+ }
+ } else {
+ if (index.column() == 0) {
+ const TimingCategoryInfo* info = GetCategoryInfo(index.row() - 2);
+ return info != nullptr ? QString(info->name) : QVariant();
+ } else {
+ if (index.row() - 2 < results.time_per_category.size()) {
+ return GetDataForColumn(index.column(), results.time_per_category[index.row() - 2]);
+ } else {
+ return QVariant();
+ }
+ }
+ }
+ }
+
+ return QVariant();
+}
+
+void ProfilerModel::updateProfilingInfo()
+{
+ results = GetTimingResultsAggregator()->GetAggregatedResults();
+ emit dataChanged(createIndex(0, 1), createIndex(rowCount() - 1, 3));
+}
+
+ProfilerWidget::ProfilerWidget(QWidget* parent) : QDockWidget(parent)
+{
+ ui.setupUi(this);
+
+ model = new ProfilerModel(this);
+ ui.treeView->setModel(model);
+
+ connect(this, SIGNAL(visibilityChanged(bool)), SLOT(setProfilingInfoUpdateEnabled(bool)));
+ connect(&update_timer, SIGNAL(timeout()), model, SLOT(updateProfilingInfo()));
+}
+
+void ProfilerWidget::setProfilingInfoUpdateEnabled(bool enable)
+{
+ if (enable) {
+ update_timer.start(100);
+ model->updateProfilingInfo();
+ } else {
+ update_timer.stop();
+ }
+}
diff --git a/src/citra_qt/debugger/profiler.h b/src/citra_qt/debugger/profiler.h
new file mode 100644
index 00000000..a6d87aa0
--- /dev/null
+++ b/src/citra_qt/debugger/profiler.h
@@ -0,0 +1,50 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <QAbstractItemModel>
+#include <QDockWidget>
+#include <QTimer>
+#include "ui_profiler.h"
+
+#include "common/profiler_reporting.h"
+
+class ProfilerModel : public QAbstractItemModel
+{
+ Q_OBJECT
+
+public:
+ ProfilerModel(QObject* parent);
+
+ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
+ QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override;
+ QModelIndex parent(const QModelIndex& child) const override;
+ int columnCount(const QModelIndex& parent = QModelIndex()) const override;
+ int rowCount(const QModelIndex& parent = QModelIndex()) const override;
+ QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
+
+public slots:
+ void updateProfilingInfo();
+
+private:
+ Common::Profiling::AggregatedFrameResult results;
+};
+
+class ProfilerWidget : public QDockWidget
+{
+ Q_OBJECT
+
+public:
+ ProfilerWidget(QWidget* parent = 0);
+
+private slots:
+ void setProfilingInfoUpdateEnabled(bool enable);
+
+private:
+ Ui::Profiler ui;
+ ProfilerModel* model;
+
+ QTimer update_timer;
+};
diff --git a/src/citra_qt/debugger/profiler.ui b/src/citra_qt/debugger/profiler.ui
new file mode 100644
index 00000000..d3c9a9a1
--- /dev/null
+++ b/src/citra_qt/debugger/profiler.ui
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Profiler</class>
+ <widget class="QDockWidget" name="Profiler">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Profiler</string>
+ </property>
+ <widget class="QWidget" name="dockWidgetContents">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QTreeView" name="treeView">
+ <property name="alternatingRowColors">
+ <bool>true</bool>
+ </property>
+ <property name="uniformRowHeights">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index 881c7d33..e3db3c20 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -35,6 +35,7 @@
#include "debugger/graphics_cmdlists.h"
#include "debugger/graphics_framebuffer.h"
#include "debugger/graphics_vertex_shader.h"
+#include "debugger/profiler.h"
#include "core/settings.h"
#include "core/system.h"
@@ -57,6 +58,10 @@ GMainWindow::GMainWindow()
render_window = new GRenderWindow;
render_window->hide();
+ profilerWidget = new ProfilerWidget(this);
+ addDockWidget(Qt::BottomDockWidgetArea, profilerWidget);
+ profilerWidget->hide();
+
disasmWidget = new DisassemblerWidget(this, render_window->GetEmuThread());
addDockWidget(Qt::BottomDockWidgetArea, disasmWidget);
disasmWidget->hide();
@@ -90,6 +95,7 @@ GMainWindow::GMainWindow()
graphicsVertexShaderWidget->hide();
QMenu* debug_menu = ui.menu_View->addMenu(tr("Debugging"));
+ debug_menu->addAction(profilerWidget->toggleViewAction());
debug_menu->addAction(disasmWidget->toggleViewAction());
debug_menu->addAction(registersWidget->toggleViewAction());
debug_menu->addAction(callstackWidget->toggleViewAction());
diff --git a/src/citra_qt/main.h b/src/citra_qt/main.h
index dd53489d..9b57c577 100644
--- a/src/citra_qt/main.h
+++ b/src/citra_qt/main.h
@@ -11,6 +11,7 @@
class GImageInfo;
class GRenderWindow;
+class ProfilerWidget;
class DisassemblerWidget;
class RegistersWidget;
class CallstackWidget;
@@ -54,6 +55,7 @@ private:
GRenderWindow* render_window;
+ ProfilerWidget* profilerWidget;
DisassemblerWidget* disasmWidget;
RegistersWidget* registersWidget;
CallstackWidget* callstackWidget;