summaryrefslogtreecommitdiff
path: root/src/citra_qt/debugger
diff options
context:
space:
mode:
authorGravatar Tony Wasserka2015-03-07 15:30:40 +0100
committerGravatar Tony Wasserka2015-03-07 15:30:40 +0100
commit93e32bce72905ac1bd0a5e75066fda5e6b7bf250 (patch)
tree4530e9d8db22955416543899b6c0e59abf8b9732 /src/citra_qt/debugger
parentMerge pull request #630 from archshift/swap (diff)
parentProfiler: Implement QPCClock to get better precision on Win32 (diff)
downloadyuzu-93e32bce72905ac1bd0a5e75066fda5e6b7bf250.tar.gz
yuzu-93e32bce72905ac1bd0a5e75066fda5e6b7bf250.tar.xz
yuzu-93e32bce72905ac1bd0a5e75066fda5e6b7bf250.zip
Merge pull request #538 from yuriks/perf-stat
Add profiling infrastructure and widget
Diffstat (limited to 'src/citra_qt/debugger')
-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
3 files changed, 221 insertions, 0 deletions
diff --git a/src/citra_qt/debugger/profiler.cpp b/src/citra_qt/debugger/profiler.cpp
new file mode 100644
index 000000000..ae0568b6a
--- /dev/null
+++ b/src/citra_qt/debugger/profiler.cpp
@@ -0,0 +1,138 @@
1// Copyright 2015 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "profiler.h"
6
7#include "common/profiler_reporting.h"
8
9using namespace Common::Profiling;
10
11static QVariant GetDataForColumn(int col, const AggregatedDuration& duration)
12{
13 static auto duration_to_float = [](Duration dur) -> float {
14 using FloatMs = std::chrono::duration<float, std::chrono::milliseconds::period>;
15 return std::chrono::duration_cast<FloatMs>(dur).count();
16 };
17
18 switch (col) {
19 case 1: return duration_to_float(duration.avg);
20 case 2: return duration_to_float(duration.min);
21 case 3: return duration_to_float(duration.max);
22 default: return QVariant();
23 }
24}
25
26static const TimingCategoryInfo* GetCategoryInfo(int id)
27{
28 const auto& categories = GetProfilingManager().GetTimingCategoriesInfo();
29 if (id >= categories.size()) {
30 return nullptr;
31 } else {
32 return &categories[id];
33 }
34}
35
36ProfilerModel::ProfilerModel(QObject* parent) : QAbstractItemModel(parent)
37{
38 updateProfilingInfo();
39 const auto& categories = GetProfilingManager().GetTimingCategoriesInfo();
40 results.time_per_category.resize(categories.size());
41}
42
43QVariant ProfilerModel::headerData(int section, Qt::Orientation orientation, int role) const
44{
45 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
46 switch (section) {
47 case 0: return tr("Category");
48 case 1: return tr("Avg");
49 case 2: return tr("Min");
50 case 3: return tr("Max");
51 }
52 }
53
54 return QVariant();
55}
56
57QModelIndex ProfilerModel::index(int row, int column, const QModelIndex& parent) const
58{
59 return createIndex(row, column);
60}
61
62QModelIndex ProfilerModel::parent(const QModelIndex& child) const
63{
64 return QModelIndex();
65}
66
67int ProfilerModel::columnCount(const QModelIndex& parent) const
68{
69 return 4;
70}
71
72int ProfilerModel::rowCount(const QModelIndex& parent) const
73{
74 if (parent.isValid()) {
75 return 0;
76 } else {
77 return results.time_per_category.size() + 2;
78 }
79}
80
81QVariant ProfilerModel::data(const QModelIndex& index, int role) const
82{
83 if (role == Qt::DisplayRole) {
84 if (index.row() == 0) {
85 if (index.column() == 0) {
86 return tr("Frame");
87 } else {
88 return GetDataForColumn(index.column(), results.frame_time);
89 }
90 } else if (index.row() == 1) {
91 if (index.column() == 0) {
92 return tr("Frame (with swapping)");
93 } else {
94 return GetDataForColumn(index.column(), results.interframe_time);
95 }
96 } else {
97 if (index.column() == 0) {
98 const TimingCategoryInfo* info = GetCategoryInfo(index.row() - 2);
99 return info != nullptr ? QString(info->name) : QVariant();
100 } else {
101 if (index.row() - 2 < results.time_per_category.size()) {
102 return GetDataForColumn(index.column(), results.time_per_category[index.row() - 2]);
103 } else {
104 return QVariant();
105 }
106 }
107 }
108 }
109
110 return QVariant();
111}
112
113void ProfilerModel::updateProfilingInfo()
114{
115 results = GetTimingResultsAggregator()->GetAggregatedResults();
116 emit dataChanged(createIndex(0, 1), createIndex(rowCount() - 1, 3));
117}
118
119ProfilerWidget::ProfilerWidget(QWidget* parent) : QDockWidget(parent)
120{
121 ui.setupUi(this);
122
123 model = new ProfilerModel(this);
124 ui.treeView->setModel(model);
125
126 connect(this, SIGNAL(visibilityChanged(bool)), SLOT(setProfilingInfoUpdateEnabled(bool)));
127 connect(&update_timer, SIGNAL(timeout()), model, SLOT(updateProfilingInfo()));
128}
129
130void ProfilerWidget::setProfilingInfoUpdateEnabled(bool enable)
131{
132 if (enable) {
133 update_timer.start(100);
134 model->updateProfilingInfo();
135 } else {
136 update_timer.stop();
137 }
138}
diff --git a/src/citra_qt/debugger/profiler.h b/src/citra_qt/debugger/profiler.h
new file mode 100644
index 000000000..a6d87aa0f
--- /dev/null
+++ b/src/citra_qt/debugger/profiler.h
@@ -0,0 +1,50 @@
1// Copyright 2015 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <QAbstractItemModel>
8#include <QDockWidget>
9#include <QTimer>
10#include "ui_profiler.h"
11
12#include "common/profiler_reporting.h"
13
14class ProfilerModel : public QAbstractItemModel
15{
16 Q_OBJECT
17
18public:
19 ProfilerModel(QObject* parent);
20
21 QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
22 QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override;
23 QModelIndex parent(const QModelIndex& child) const override;
24 int columnCount(const QModelIndex& parent = QModelIndex()) const override;
25 int rowCount(const QModelIndex& parent = QModelIndex()) const override;
26 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
27
28public slots:
29 void updateProfilingInfo();
30
31private:
32 Common::Profiling::AggregatedFrameResult results;
33};
34
35class ProfilerWidget : public QDockWidget
36{
37 Q_OBJECT
38
39public:
40 ProfilerWidget(QWidget* parent = 0);
41
42private slots:
43 void setProfilingInfoUpdateEnabled(bool enable);
44
45private:
46 Ui::Profiler ui;
47 ProfilerModel* model;
48
49 QTimer update_timer;
50};
diff --git a/src/citra_qt/debugger/profiler.ui b/src/citra_qt/debugger/profiler.ui
new file mode 100644
index 000000000..d3c9a9a1f
--- /dev/null
+++ b/src/citra_qt/debugger/profiler.ui
@@ -0,0 +1,33 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<ui version="4.0">
3 <class>Profiler</class>
4 <widget class="QDockWidget" name="Profiler">
5 <property name="geometry">
6 <rect>
7 <x>0</x>
8 <y>0</y>
9 <width>400</width>
10 <height>300</height>
11 </rect>
12 </property>
13 <property name="windowTitle">
14 <string>Profiler</string>
15 </property>
16 <widget class="QWidget" name="dockWidgetContents">
17 <layout class="QVBoxLayout" name="verticalLayout">
18 <item>
19 <widget class="QTreeView" name="treeView">
20 <property name="alternatingRowColors">
21 <bool>true</bool>
22 </property>
23 <property name="uniformRowHeights">
24 <bool>true</bool>
25 </property>
26 </widget>
27 </item>
28 </layout>
29 </widget>
30 </widget>
31 <resources/>
32 <connections/>
33</ui>