diff --git a/qrenderdoc/Windows/Dialogs/PerformanceCounterSelection.cpp b/qrenderdoc/Windows/Dialogs/PerformanceCounterSelection.cpp index 016ca6d41..cc010f519 100644 --- a/qrenderdoc/Windows/Dialogs/PerformanceCounterSelection.cpp +++ b/qrenderdoc/Windows/Dialogs/PerformanceCounterSelection.cpp @@ -27,8 +27,12 @@ #include "Code/Interface/QRDInterface.h" #include "ui_PerformanceCounterSelection.h" +#include #include +#define JSON_ID "rdocPerformanceCounterSettings" +#define JSON_VER 1 + namespace { enum class CounterFamily @@ -88,6 +92,107 @@ PerformanceCounterSelection::PerformanceCounterSelection(ICaptureContext &ctx, Q } }); + connect(ui->save, &QPushButton::pressed, [&]() -> void { + QString filename = RDDialog::getSaveFileName(this, tr("Save File"), QDir::homePath(), + tr("Performance Counter Settings (*.json)")); + + if(filename.isEmpty()) + return; + + QVariantList counterIds; + for(auto v : m_SelectedCounters.keys()) + { + const Uuid uuid = m_CounterToUuid[v]; + QVariantList e; + + for(const auto b : uuid.bytes) + { + e.append(b); + } + + counterIds.append(QVariant{e}); + } + + QVariantMap doc; + doc[QLatin1String{"counters"}] = counterIds; + + QFile f(filename); + if(f.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) + { + SaveToJSON(doc, f, JSON_ID, JSON_VER); + } + else + { + RDDialog::critical(this, tr("Error saving config"), + tr("Couldn't open path %1 for write.").arg(filename)); + } + }); + + connect(ui->load, &QPushButton::pressed, [&]() -> void { + QString filename = RDDialog::getOpenFileName(this, tr("Load file"), QDir::homePath(), + tr("Performance Counter Settings (*.json)")); + + if(filename.isEmpty()) + return; + + QVariantMap doc; + QFile f(filename); + if(f.open(QIODevice::ReadOnly | QIODevice::Text)) + { + LoadFromJSON(doc, f, JSON_ID, JSON_VER); + + std::set selectedCounters; + + QVariantList counters = doc[QLatin1String{"counters"}].toList(); + + for(const auto &counter : counters) + { + QVariantList bytes = counter.toList(); + Uuid uuid; + + /// TODO assert counter.size () == 4 + + for(int i = 0; i < 4; ++i) + { + uuid.bytes[i] = bytes[i].toUInt(); + } + + selectedCounters.insert(uuid); + } + + // We we walk over the complete tree, and toggle everything so it + // matches the settings + QTreeWidgetItemIterator it(ui->counterTree); + while(*it) + { + const auto id = (*it)->data(0, Qt::UserRole + 2); + if(id.isValid()) + { + const GPUCounter counter = (GPUCounter)id.toUInt(); + + if(!m_CounterToUuid.contains(counter)) + continue; + + (*it)->setCheckState( + 0, (selectedCounters.find(m_CounterToUuid[counter]) != selectedCounters.end()) + ? Qt::Checked + : Qt::Unchecked); + } + + // The loop above will uncheck all unknown counters, and not crash if some counter is no + // longer present, or unknown + + ++it; + } + } + else + { + RDDialog::critical(this, tr("Error loading config"), + tr("Couldn't open path %1 for reading.").arg(filename)); + } + + }); + connect(ui->counterTree, &QTreeWidget::itemChanged, [&](QTreeWidgetItem *item, int) -> void { const auto d = item->data(0, Qt::UserRole + 2); @@ -98,12 +203,12 @@ PerformanceCounterSelection::PerformanceCounterSelection(ICaptureContext &ctx, Q // Add auto listItem = new QListWidgetItem(ui->enabledCounters); listItem->setText(item->text(0)); - m_SelectedCounters.insert(d.toUInt(), listItem); + m_SelectedCounters.insert((GPUCounter)d.toUInt(), listItem); } else { // Remove - auto listItem = m_SelectedCounters.take(d.toUInt()); + auto listItem = m_SelectedCounters.take((GPUCounter)d.toUInt()); delete listItem; } } @@ -124,6 +229,9 @@ PerformanceCounterSelection::PerformanceCounterSelection(ICaptureContext &ctx, Q for(const auto desc : counters) { + m_CounterToUuid[desc.counterID] = desc.uuid; + m_UuidToCounter[desc.uuid] = desc.counterID; + const CounterFamily family = GetCounterFamily(desc.counterID); if(family != currentFamily) { @@ -176,7 +284,7 @@ PerformanceCounterSelection::~PerformanceCounterSelection() delete ui; } -QList PerformanceCounterSelection::GetSelectedCounters() const +QList PerformanceCounterSelection::GetSelectedCounters() const { return m_SelectedCounters.keys(); } diff --git a/qrenderdoc/Windows/Dialogs/PerformanceCounterSelection.h b/qrenderdoc/Windows/Dialogs/PerformanceCounterSelection.h index d82ee4e00..5579ab563 100644 --- a/qrenderdoc/Windows/Dialogs/PerformanceCounterSelection.h +++ b/qrenderdoc/Windows/Dialogs/PerformanceCounterSelection.h @@ -24,6 +24,7 @@ #include #include +#include "Code/Interface/QRDInterface.h" namespace Ui { @@ -41,11 +42,13 @@ public: explicit PerformanceCounterSelection(ICaptureContext &ctx, QWidget *parent = 0); ~PerformanceCounterSelection(); - QList GetSelectedCounters() const; + QList GetSelectedCounters() const; private: Ui::PerformanceCounterSelection *ui; ICaptureContext &m_Ctx; - QMap m_SelectedCounters; + QMap m_SelectedCounters; + QMap m_CounterToUuid; + QMap m_UuidToCounter; }; diff --git a/qrenderdoc/Windows/PerformanceCounterViewer.cpp b/qrenderdoc/Windows/PerformanceCounterViewer.cpp index 9bbbcf266..66244c0a1 100644 --- a/qrenderdoc/Windows/PerformanceCounterViewer.cpp +++ b/qrenderdoc/Windows/PerformanceCounterViewer.cpp @@ -79,7 +79,7 @@ PerformanceCounterViewer::PerformanceCounterViewer(ICaptureContext &ctx, QWidget PerformanceCounterSelection pcs(m_Ctx, this); if(RDDialog::show(&pcs) == QDialog::Accepted) { - const QList selectedCounters = pcs.GetSelectedCounters(); + const QList selectedCounters = pcs.GetSelectedCounters(); bool done = false; m_Ctx.Replay().AsyncInvoke([=, &done](IReplayController *controller) -> void {