Skip to content

Commit eab6f95

Browse files
authored
Perf Counters Displayed Using AvailableMetrics and PerfMetricsData (#389)
Perf counter parsing with available metrics and perf metrics data
1 parent 870d5d5 commit eab6f95

14 files changed

+692
-186
lines changed

dive_core/available_metrics.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,17 @@ MetricType AvailableMetrics::GetMetricType(const std::string& key) const
122122
return info ? info->m_metric_type : MetricType::kUnknown;
123123
}
124124

125+
std::vector<std::string> AvailableMetrics::GetAllMetricKeys() const
126+
{
127+
std::vector<std::string> keys;
128+
keys.reserve(m_metrics.size());
129+
130+
for (const auto& pair : m_metrics)
131+
{
132+
keys.push_back(pair.first);
133+
}
134+
135+
return keys;
136+
}
137+
125138
} // namespace Dive

dive_core/available_metrics.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@
1818

1919
#include <cstdint>
2020
#include <filesystem>
21+
#include <map>
2122
#include <string>
22-
#include <unordered_map>
2323
#include <optional>
2424
#include <memory>
25+
#include <vector>
2526

2627
namespace Dive
2728
{
@@ -59,9 +60,12 @@ class AvailableMetrics
5960
// Get the metric type for a given key, return kUnknown if not found.
6061
MetricType GetMetricType(const std::string& key) const;
6162

63+
// Get all available metric keys
64+
std::vector<std::string> GetAllMetricKeys() const;
65+
6266
private:
6367
AvailableMetrics() = default;
64-
std::unordered_map<std::string, MetricInfo> m_metrics;
68+
std::map<std::string, MetricInfo> m_metrics;
6569
};
6670

6771
} // namespace Dive

dive_core/perf_metrics_data.cpp

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,6 @@ namespace Dive
3838

3939
namespace
4040
{
41-
constexpr std::array kFixedHeaders = { "ContextID", "ProcessID", "FrameID",
42-
"CmdBufferID", "DrawID", "DrawType",
43-
"DrawLabel", "ProgramID", "LRZState" };
4441

4542
struct ParseHeadersResult
4643
{
@@ -59,7 +56,7 @@ std::optional<ParseHeadersResult> ParseHeaders(const std::string& line,
5956
int column_index = 0;
6057
while (StringUtils::GetTrimmedField(header_ss, header_field, ','))
6158
{
62-
if (column_index < kFixedHeaders.size())
59+
if (column_index < kFixedPerfMetricsDataHeaderCount)
6360
{
6461
if (header_field != kFixedHeaders[column_index])
6562
return std::nullopt; // Fixed header mismatch
@@ -71,7 +68,7 @@ std::optional<ParseHeadersResult> ParseHeaders(const std::string& line,
7168
}
7269
column_index++;
7370
}
74-
if (column_index < kFixedHeaders.size())
71+
if (column_index < kFixedPerfMetricsDataHeaderCount)
7572
{
7673
return std::nullopt; // Not enough columns
7774
}
@@ -81,7 +78,7 @@ std::optional<ParseHeadersResult> ParseHeaders(const std::string& line,
8178

8279
std::optional<PerfMetricsRecord> ParseRecordFixedFields(const std::vector<std::string>& fields)
8380
{
84-
if (fields.size() < kFixedHeaders.size())
81+
if (fields.size() < kFixedPerfMetricsDataHeaderCount)
8582
{
8683
return std::nullopt;
8784
}
@@ -120,7 +117,7 @@ bool ParseMetrics(const std::vector<std::string>& fields,
120117
{
121118
for (size_t i = 0; i < metric_infos.size(); ++i)
122119
{
123-
const std::string& value_str = fields[kFixedHeaders.size() + i];
120+
const std::string& value_str = fields[kFixedPerfMetricsDataHeaderCount + i];
124121
const MetricInfo* info = metric_infos[i];
125122
if (info == nullptr)
126123
{
@@ -203,7 +200,7 @@ std::unique_ptr<AvailableMetrics> available_metrics)
203200
fields.push_back(field);
204201
}
205202

206-
if (fields.size() != kFixedHeaders.size() + metric_names.size())
203+
if (fields.size() != kFixedPerfMetricsDataHeaderCount + metric_names.size())
207204
{
208205
continue; // Skip malformed lines
209206
}
@@ -609,7 +606,7 @@ void PerfMetricsDataProvider::Analyze(const CommandHierarchy* command_hierarchy)
609606
const std::vector<std::string> PerfMetricsDataProvider::GetRecordHeader() const
610607
{
611608
std::vector<std::string> full_header;
612-
full_header.reserve(kFixedHeaders.size() + GetMetricsNames().size());
609+
full_header.reserve(kFixedPerfMetricsDataHeaderCount + GetMetricsNames().size());
613610
for (const auto& header : kFixedHeaders)
614611
{
615612
full_header.push_back(header);

dive_core/perf_metrics_data.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,45 @@
2525
#include <functional>
2626
#include <utility>
2727
#include <tuple>
28+
#include <array>
2829

2930
namespace Dive
3031
{
3132

33+
enum FixedPerfMetricsDataHeaders : uint32_t
34+
{
35+
kContextID,
36+
kProcessID,
37+
kFrameID,
38+
kCmdBufferID,
39+
kDrawID,
40+
kDrawType,
41+
kDrawLabel,
42+
kProgramID,
43+
kLRZState,
44+
kFixedPerfMetricsDataHeaderCount
45+
};
46+
47+
constexpr std::array kHeaderMap = {
48+
std::pair(kContextID, "ContextID"), std::pair(kProcessID, "ProcessID"),
49+
std::pair(kFrameID, "FrameID"), std::pair(kCmdBufferID, "CmdBufferID"),
50+
std::pair(kDrawID, "DrawID"), std::pair(kDrawType, "DrawType"),
51+
std::pair(kDrawLabel, "DrawLabel"), std::pair(kProgramID, "ProgramID"),
52+
std::pair(kLRZState, "LRZState")
53+
};
54+
55+
static_assert(kHeaderMap.size() == kFixedPerfMetricsDataHeaderCount,
56+
"ERROR: FixedPerfMetricsDataHeaders and kHeaderMap are out of sync!");
57+
58+
inline constexpr std::array<const char*, kFixedPerfMetricsDataHeaderCount> kFixedHeaders = [] {
59+
std::array<const char*, kFixedPerfMetricsDataHeaderCount> arr{};
60+
for (const auto& pair : kHeaderMap)
61+
{
62+
arr[pair.first] = pair.second;
63+
}
64+
return arr;
65+
}();
66+
3267
class CommandHierarchy;
3368
class AvailableMetrics;
3469
struct MetricInfo;

ui/analyze_window.cpp

Lines changed: 38 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@
3232
#include <QStandardItemModel>
3333
#include <QVBoxLayout>
3434
#include <filesystem>
35+
#include <optional>
3536
#include <qapplication.h>
37+
#include <qtemporarydir.h>
3638
#include <string>
3739

3840
#include "absl/status/status.h"
@@ -58,7 +60,11 @@ void AttemptDeletingTemporaryLocalFile(const std::filesystem::path &file_path)
5860
// =================================================================================================
5961
// AnalyzeDialog
6062
// =================================================================================================
61-
AnalyzeDialog::AnalyzeDialog(QWidget *parent)
63+
AnalyzeDialog::AnalyzeDialog(
64+
std::optional<std::reference_wrapper<const Dive::AvailableMetrics>> available_metrics,
65+
QWidget *parent) :
66+
QDialog(parent),
67+
m_available_metrics(available_metrics)
6268
{
6369
qDebug() << "AnalyzeDialog created.";
6470

@@ -249,59 +255,41 @@ void AnalyzeDialog::ShowErrorMessage(const std::string &err_msg)
249255
//--------------------------------------------------------------------------------------------------
250256
void AnalyzeDialog::PopulateMetrics()
251257
{
252-
QFile file(":/resources/available_metrics.csv");
253-
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
258+
if (m_available_metrics.has_value())
254259
{
255-
std::cout << "Could not open file:" << file.errorString().toStdString() << std::endl;
256-
qDebug() << "Could not open file:" << file.errorString();
257-
return;
258-
}
259-
260-
QTextStream in(&file);
261-
262-
// Read and discard the first line (headers)
263-
if (!in.atEnd())
264-
{
265-
in.readLine();
266-
}
260+
// Get the list of all available metrics
261+
std::vector<std::string> all_keys = m_available_metrics->get().GetAllMetricKeys();
267262

268-
while (!in.atEnd())
269-
{
270-
QString line = in.readLine();
271-
QStringList fields = line.split(',');
263+
for (const auto &key : all_keys)
264+
{
265+
const Dive::MetricInfo *info = m_available_metrics->get().GetMetricInfo(key);
266+
if (info)
267+
{
268+
CsvItem item;
269+
item.id = info->m_metric_id;
270+
item.type = info->m_metric_type;
271+
item.key = QString::fromStdString(key);
272+
item.name = QString::fromStdString(info->m_name);
273+
item.description = QString::fromStdString(info->m_description);
274+
m_csv_items->append(item);
275+
}
276+
}
272277

273-
if (fields.size() == 5)
278+
// Populate the metrics list
279+
for (const auto &item : *m_csv_items)
274280
{
275-
CsvItem item;
276-
item.id = fields[0].replace('"', "");
277-
;
278-
item.type = fields[1].replace('"', "");
279-
;
280-
item.key = fields[2].replace('"', "");
281-
;
282-
item.name = fields[3].replace('"', "");
283-
;
284-
item.description = fields[4].replace('"', "");
285-
;
286-
m_csv_items->append(item);
281+
QListWidgetItem *csv_item = new QListWidgetItem(item.name);
282+
csv_item->setData(kDataRole, item.key);
283+
csv_item->setFlags(csv_item->flags() | Qt::ItemIsUserCheckable);
284+
csv_item->setCheckState(Qt::Unchecked);
285+
m_metrics_list->addItem(csv_item);
287286
}
288-
}
289-
file.close();
290287

291-
// Populate the metrics list
292-
for (const auto &item : *m_csv_items)
293-
{
294-
QListWidgetItem *csv_item = new QListWidgetItem(item.name);
295-
csv_item->setData(kDataRole, item.key);
296-
csv_item->setFlags(csv_item->flags() | Qt::ItemIsUserCheckable);
297-
csv_item->setCheckState(Qt::Unchecked);
298-
m_metrics_list->addItem(csv_item);
288+
// Add spacer so that all metrics are visible at the end of the list.
289+
QListWidgetItem *spacer = new QListWidgetItem();
290+
spacer->setFlags(spacer->flags() & ~Qt::ItemIsSelectable);
291+
m_metrics_list->addItem(spacer);
299292
}
300-
301-
// Add spacer so that all metrics are visible at the end of the list.
302-
QListWidgetItem *spacer = new QListWidgetItem();
303-
spacer->setFlags(spacer->flags() & ~Qt::ItemIsSelectable);
304-
m_metrics_list->addItem(spacer);
305293
}
306294

307295
//--------------------------------------------------------------------------------------------------
@@ -757,12 +745,13 @@ void AnalyzeDialog::OnReplay()
757745
}
758746
WaitForReplay(*device);
759747
qDebug() << "Loading perf counter data: " << perf_counter_csv.string().c_str();
760-
emit OnDisplayPerfCounterResults(QString::fromStdString(perf_counter_csv.string()));
748+
749+
emit OnDisplayPerfCounterResults(perf_counter_csv.string(), m_available_metrics);
761750
}
762751
else
763752
{
764753
qDebug() << "Cleared perf counter data";
765-
emit OnDisplayPerfCounterResults("");
754+
emit OnDisplayPerfCounterResults("", std::nullopt);
766755
}
767756

768757
// Run the gpu_time replay

ui/analyze_window.h

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <QDialog>
1818
#include "capture_service/device_mgr.h"
1919
#include "package_filter.h"
20+
#include "dive_core/available_metrics.h"
2021

2122
#pragma once
2223

@@ -35,25 +36,27 @@ class MainWindow;
3536

3637
namespace Dive
3738
{
38-
class SelectedCaptureFiles;
39+
class AvailableMetrics;
3940
} // namespace Dive
4041

4142
class AnalyzeDialog : public QDialog
4243
{
4344
// Data structure to hold a single item from the CSV
4445
struct CsvItem
4546
{
46-
QString id;
47-
QString type;
48-
QString key;
49-
QString name;
50-
QString description;
47+
QString id;
48+
Dive::MetricType type;
49+
QString key;
50+
QString name;
51+
QString description;
5152
};
5253

5354
Q_OBJECT
5455

5556
public:
56-
AnalyzeDialog(QWidget *parent = 0);
57+
AnalyzeDialog(
58+
std::optional<std::reference_wrapper<const Dive::AvailableMetrics>> available_metrics,
59+
QWidget *parent = nullptr);
5760
~AnalyzeDialog();
5861
void UpdateDeviceList(bool isInitialized);
5962
void SetSelectedCaptureFile(const QString &filePath);
@@ -64,7 +67,9 @@ private slots:
6467
void OnReplay();
6568
signals:
6669
void OnNewFileOpened(const QString &file_path);
67-
void OnDisplayPerfCounterResults(const QString &file_path);
70+
void OnDisplayPerfCounterResults(
71+
const std::filesystem::path &file_path,
72+
std::optional<std::reference_wrapper<const Dive::AvailableMetrics>> available_metrics);
6873
void OnDisplayGpuTimingResults(const QString &file_path);
6974
void ReloadCapture(const QString &file_path);
7075

@@ -136,7 +141,7 @@ private slots:
136141
QString m_selected_capture_file_string;
137142
QVector<CsvItem> *m_csv_items;
138143
std::vector<std::string> *m_enabled_metrics_vector;
139-
144+
std::optional<std::reference_wrapper<const Dive::AvailableMetrics>> m_available_metrics;
140145
// Used to store a csv item's key in the enabled metrics vector.
141146
const int kDataRole = Qt::UserRole + 1;
142147
const int kDefaultFrameCount = 3;

ui/gfxr_vulkan_command_filter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,6 @@ void GfxrVulkanCommandFilter::OnFilterGfxrVulkanCommandChange(const QString &fil
8383
m_command_hierarchy_view.scrollToTop();
8484

8585
m_command_hierarchy_view.expandAll();
86+
87+
emit FilterChanged();
8688
}

ui/gfxr_vulkan_command_filter.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public slots:
3434
void OnFilterGfxrVulkanCommandChange(const QString &filter_mode);
3535

3636
signals:
37-
void FilterTextChanged(const QString &text);
37+
void FilterChanged();
3838

3939
private:
4040
DiveTreeView &m_command_hierarchy_view;

0 commit comments

Comments
 (0)