diff --git a/qrenderdoc/Windows/Dialogs/PerformanceCounterSelection.cpp b/qrenderdoc/Windows/Dialogs/PerformanceCounterSelection.cpp index cc010f519..9a1bc5e94 100644 --- a/qrenderdoc/Windows/Dialogs/PerformanceCounterSelection.cpp +++ b/qrenderdoc/Windows/Dialogs/PerformanceCounterSelection.cpp @@ -62,223 +62,128 @@ CounterFamily GetCounterFamily(GPUCounter counter) return CounterFamily::Generic; } -const char *ToString(CounterFamily family) +QString ToString(CounterFamily family) { switch(family) { - case CounterFamily::AMD: return "AMD"; - case CounterFamily::Generic: return "Generic"; - case CounterFamily::Intel: return "Intel"; - case CounterFamily::NVIDIA: return "NVIDIA"; - case CounterFamily::Unknown: return "Unknown"; + case CounterFamily::AMD: return lit("AMD"); + case CounterFamily::Generic: return lit("Generic"); + case CounterFamily::Intel: return lit("Intel"); + case CounterFamily::NVIDIA: return lit("NVIDIA"); + case CounterFamily::Unknown: return lit("Unknown"); } - return nullptr; + return QString(); } } +const int PerformanceCounterSelection::CounterDescriptionRole = Qt::UserRole + 1; +const int PerformanceCounterSelection::CounterIdRole = Qt::UserRole + 2; + PerformanceCounterSelection::PerformanceCounterSelection(ICaptureContext &ctx, QWidget *parent) : QDialog(parent), ui(new Ui::PerformanceCounterSelection), m_Ctx(ctx) { ui->setupUi(this); - connect(ui->counterTree, &QTreeWidget::itemEntered, [&](QTreeWidgetItem *item, int) -> void { - const auto d = item->data(0, Qt::UserRole + 1); + connect(ui->counterTree, &QTreeWidget::itemEntered, [this](QTreeWidgetItem *item, int) -> void { + const QVariant d = item->data(0, CounterDescriptionRole); if(d.isValid()) { ui->counterDescription->setText( - QString(QLatin1String("%1
%2")).arg(item->text(0)).arg(d.toString())); + QString(lit("%1
%2")).arg(item->text(0)).arg(d.toString())); } }); - connect(ui->save, &QPushButton::pressed, [&]() -> void { - QString filename = RDDialog::getSaveFileName(this, tr("Save File"), QDir::homePath(), - tr("Performance Counter Settings (*.json)")); + connect(ui->save, &QPushButton::pressed, this, &PerformanceCounterSelection::Save); + connect(ui->load, &QPushButton::pressed, this, &PerformanceCounterSelection::Load); + connect(ui->sampleCounters, &QPushButton::pressed, this, &PerformanceCounterSelection::accept); - 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); + connect(ui->counterTree, &QTreeWidget::itemChanged, [this](QTreeWidgetItem *item, int) -> void { + const QVariant d = item->data(0, CounterIdRole); if(d.isValid()) { if(item->checkState(0) == Qt::Checked) { // Add - auto listItem = new QListWidgetItem(ui->enabledCounters); + QListWidgetItem *listItem = new QListWidgetItem(ui->enabledCounters); listItem->setText(item->text(0)); m_SelectedCounters.insert((GPUCounter)d.toUInt(), listItem); } else { // Remove - auto listItem = m_SelectedCounters.take((GPUCounter)d.toUInt()); + QListWidgetItem *listItem = m_SelectedCounters.take((GPUCounter)d.toUInt()); delete listItem; } } }); - connect(ui->sampleCounters, &QPushButton::pressed, [&]() -> void { this->accept(); }); - ui->counterTree->setMouseTracking(true); - auto showCounters = [&](const QVector &counters) -> void { - ui->counterTree->clear(); - ui->enabledCounters->clear(); - - QTreeWidgetItem *currentRoot = NULL; - CounterFamily currentFamily = CounterFamily::Unknown; - - std::unordered_map categories; - - for(const auto desc : counters) + ctx.Replay().AsyncInvoke([this](IReplayController *controller) -> void { + QVector counterDescriptions; + for(const GPUCounter counter : controller->EnumerateCounters()) { - m_CounterToUuid[desc.counterID] = desc.uuid; - m_UuidToCounter[desc.uuid] = desc.counterID; - - const CounterFamily family = GetCounterFamily(desc.counterID); - if(family != currentFamily) - { - currentRoot = new QTreeWidgetItem(ui->counterTree); - currentRoot->setText(0, QLatin1String{ToString(family)}); - - categories.clear(); - - currentFamily = family; - } - - QTreeWidgetItem *categoryItem = nullptr; - - const auto category = std::string{desc.category}; - auto categoryIterator = categories.find(category); - - if(categoryIterator == categories.end()) - { - auto item = new QTreeWidgetItem{currentRoot}; - item->setText(0, desc.category); - categories[category] = item; - categoryItem = item; - } - else - { - categoryItem = categoryIterator->second; - } - - auto counterItem = new QTreeWidgetItem{categoryItem}; - counterItem->setText(0, desc.name); - counterItem->setData(0, Qt::UserRole + 1, desc.description); - counterItem->setData(0, Qt::UserRole + 2, (uint32_t)desc.counterID); - counterItem->setCheckState(0, Qt::Unchecked); - } - }; - - ctx.Replay().AsyncInvoke([=](IReplayController *controller) -> void { - QVector desc; - for(const auto counter : controller->EnumerateCounters()) - { - desc.append(controller->DescribeCounter(counter)); + counterDescriptions.append(controller->DescribeCounter(counter)); } - GUIInvoke::call([=]() -> void { showCounters(desc); }); + GUIInvoke::call([counterDescriptions, this]() -> void { SetCounters(counterDescriptions); }); }); } +void PerformanceCounterSelection::SetCounters(const QVector &descriptions) +{ + ui->counterTree->clear(); + ui->enabledCounters->clear(); + + QTreeWidgetItem *currentRoot = NULL; + CounterFamily currentFamily = CounterFamily::Unknown; + + std::unordered_map categories; + + for(const CounterDescription &desc : descriptions) + { + m_CounterToUuid[desc.counterID] = desc.uuid; + m_UuidToCounter[desc.uuid] = desc.counterID; + + const CounterFamily family = GetCounterFamily(desc.counterID); + if(family != currentFamily) + { + currentRoot = new QTreeWidgetItem(ui->counterTree); + currentRoot->setText(0, ToString(family)); + + categories.clear(); + + currentFamily = family; + } + + QTreeWidgetItem *categoryItem = NULL; + + const std::string category = desc.category; + auto categoryIterator = categories.find(category); + + if(categoryIterator == categories.end()) + { + QTreeWidgetItem *item = new QTreeWidgetItem(currentRoot); + item->setText(0, desc.category); + categories[category] = item; + categoryItem = item; + } + else + { + categoryItem = categoryIterator->second; + } + + QTreeWidgetItem *counterItem = new QTreeWidgetItem(categoryItem); + counterItem->setText(0, desc.name); + counterItem->setData(0, CounterDescriptionRole, desc.description); + counterItem->setData(0, CounterIdRole, (uint32_t)desc.counterID); + counterItem->setCheckState(0, Qt::Unchecked); + } +} + PerformanceCounterSelection::~PerformanceCounterSelection() { delete ui; @@ -288,3 +193,105 @@ QList PerformanceCounterSelection::GetSelectedCounters() const { return m_SelectedCounters.keys(); } + +void PerformanceCounterSelection::Save() +{ + QString filename = RDDialog::getSaveFileName(this, tr("Save File"), QDir::homePath(), + tr("Performance Counter Settings (*.json)")); + + if(filename.isEmpty()) + return; + + QVariantList counterIds; + for(const GPUCounter v : m_SelectedCounters.keys()) + { + const Uuid uuid = m_CounterToUuid[v]; + QVariantList e; + + for(const byte b : uuid.bytes) + { + e.append(b); + } + + counterIds.append(QVariant(e)); + } + + QVariantMap doc; + doc[lit("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)); + } +} + +void PerformanceCounterSelection::Load() +{ + 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[lit("counters")].toList(); + + for(const QVariant &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 QVariant 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)); + } +} \ No newline at end of file diff --git a/qrenderdoc/Windows/Dialogs/PerformanceCounterSelection.h b/qrenderdoc/Windows/Dialogs/PerformanceCounterSelection.h index 5579ab563..347eca2d6 100644 --- a/qrenderdoc/Windows/Dialogs/PerformanceCounterSelection.h +++ b/qrenderdoc/Windows/Dialogs/PerformanceCounterSelection.h @@ -44,11 +44,20 @@ public: QList GetSelectedCounters() const; +public slots: + void Save(); + void Load(); + private: + void SetCounters(const QVector &descriptions); + Ui::PerformanceCounterSelection *ui; ICaptureContext &m_Ctx; QMap m_SelectedCounters; QMap m_CounterToUuid; QMap m_UuidToCounter; + + static const int CounterDescriptionRole; + static const int CounterIdRole; }; diff --git a/qrenderdoc/Windows/Dialogs/PerformanceCounterSelection.ui b/qrenderdoc/Windows/Dialogs/PerformanceCounterSelection.ui index 50ebd8964..74cbcfd03 100644 --- a/qrenderdoc/Windows/Dialogs/PerformanceCounterSelection.ui +++ b/qrenderdoc/Windows/Dialogs/PerformanceCounterSelection.ui @@ -48,15 +48,6 @@ - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Cache miss</span></p> -<hr /> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Lorem ipsum something something about cache misses and why you don't want those to happen all the time. Not sure what to write here, given some people seem to like a high number here.</p></body></html> - diff --git a/qrenderdoc/Windows/PerformanceCounterViewer.cpp b/qrenderdoc/Windows/PerformanceCounterViewer.cpp index 66244c0a1..555fee5ec 100644 --- a/qrenderdoc/Windows/PerformanceCounterViewer.cpp +++ b/qrenderdoc/Windows/PerformanceCounterViewer.cpp @@ -53,13 +53,13 @@ static QString FormatCounterResult(const CounterResult &result, const CounterDes switch(description.unit) { - case CounterUnit::Bytes: returnValue += QLatin1String{" bytes"}; break; + case CounterUnit::Bytes: returnValue += lit(" bytes"); break; - case CounterUnit::Cycles: returnValue += QLatin1String{" cycles"}; break; + case CounterUnit::Cycles: returnValue += lit(" cycles"); break; - case CounterUnit::Percentage: returnValue += QLatin1String{" %"}; break; + case CounterUnit::Percentage: returnValue += lit(" %"); break; - case CounterUnit::Seconds: returnValue += QLatin1String{" s"}; break; + case CounterUnit::Seconds: returnValue += lit(" s"); break; case CounterUnit::Absolute: case CounterUnit::Ratio: break; @@ -75,74 +75,75 @@ PerformanceCounterViewer::PerformanceCounterViewer(ICaptureContext &ctx, QWidget m_Ctx.AddLogViewer(this); - connect(ui->captureCounters, &QToolButton::pressed, [=]() -> void { - PerformanceCounterSelection pcs(m_Ctx, this); - if(RDDialog::show(&pcs) == QDialog::Accepted) + connect(ui->captureCounters, &QToolButton::pressed, this, + &PerformanceCounterViewer::CaptureCounters); +} + +void PerformanceCounterViewer::CaptureCounters() +{ + PerformanceCounterSelection pcs(m_Ctx, this); + if(RDDialog::show(&pcs) != QDialog::Accepted) + return; + const QList selectedCounters = pcs.GetSelectedCounters(); + + bool done = false; + m_Ctx.Replay().AsyncInvoke([this, selectedCounters, &done](IReplayController *controller) -> void { + rdctype::array counters; + counters.create(selectedCounters.size()); + + QMap counterDescriptions; + + for(int i = 0; i < selectedCounters.size(); ++i) { - const QList selectedCounters = pcs.GetSelectedCounters(); - - bool done = false; - m_Ctx.Replay().AsyncInvoke([=, &done](IReplayController *controller) -> void { - rdctype::array counters; - counters.create(selectedCounters.size()); - - QMap counterDescriptions; - - for(int i = 0; i < selectedCounters.size(); ++i) - { - counters[i] = (GPUCounter)selectedCounters[i]; - counterDescriptions.insert(counters[i], controller->DescribeCounter(counters[i])); - } - - QMap counterIndex; - for(int i = 0; i < selectedCounters.size(); ++i) - { - counterIndex.insert((GPUCounter)selectedCounters[i], i); - } - - const auto results = controller->FetchCounters(counters); - - GUIInvoke::call([this, results, counterDescriptions, counterIndex]() -> void { - ui->counterResults->clear(); - - QStringList headers; - headers << QLatin1String{"EID"}; - for(const auto &cd : counterDescriptions) - { - headers << cd.name; - } - - QMap eventIdToRow; - for(const auto &result : results) - { - if(eventIdToRow.contains(result.eventID)) - continue; - eventIdToRow[result.eventID] = eventIdToRow.size(); - } - - ui->counterResults->setColumnCount(headers.size()); - ui->counterResults->setHorizontalHeaderLabels(headers); - ui->counterResults->setRowCount(eventIdToRow.size()); - ui->counterResults->verticalHeader()->hide(); - - for(int i = 0; i < (int)results.size(); ++i) - { - int row = eventIdToRow[results[i].eventID]; - ui->counterResults->setItem(row, 0, - new QTableWidgetItem(QString::number(results[i].eventID))); - ui->counterResults->setItem(row, counterIndex[results[i].counterID] + 1, - new QTableWidgetItem(FormatCounterResult( - results[i], counterDescriptions[results[i].counterID]))); - } - }); - - done = true; - }); - - ShowProgressDialog(this, QLatin1String("Capturing counters"), - [&done]() -> bool { return done; }); + counters[i] = (GPUCounter)selectedCounters[i]; + counterDescriptions.insert(counters[i], controller->DescribeCounter(counters[i])); } + + QMap counterIndex; + for(int i = 0; i < selectedCounters.size(); ++i) + { + counterIndex.insert((GPUCounter)selectedCounters[i], i); + } + + const rdctype::array results = controller->FetchCounters(counters); + + GUIInvoke::call([this, results, counterDescriptions, counterIndex]() -> void { + ui->counterResults->clear(); + + QStringList headers; + headers << lit("EID"); + for(const CounterDescription &cd : counterDescriptions) + { + headers << cd.name; + } + + QMap eventIdToRow; + for(const CounterResult &result : results) + { + if(eventIdToRow.contains(result.eventID)) + continue; + eventIdToRow[result.eventID] = eventIdToRow.size(); + } + + ui->counterResults->setColumnCount(headers.size()); + ui->counterResults->setHorizontalHeaderLabels(headers); + ui->counterResults->setRowCount(eventIdToRow.size()); + + for(int i = 0; i < (int)results.size(); ++i) + { + int row = eventIdToRow[results[i].eventID]; + ui->counterResults->setItem(row, 0, + new QTableWidgetItem(QString::number(results[i].eventID))); + ui->counterResults->setItem(row, counterIndex[results[i].counterID] + 1, + new QTableWidgetItem(FormatCounterResult( + results[i], counterDescriptions[results[i].counterID]))); + } + }); + + done = true; }); + + ShowProgressDialog(this, tr("Capturing counters"), [&done]() -> bool { return done; }); } PerformanceCounterViewer::~PerformanceCounterViewer() diff --git a/qrenderdoc/Windows/PerformanceCounterViewer.h b/qrenderdoc/Windows/PerformanceCounterViewer.h index 6d4b85ad9..8b2c8aeff 100644 --- a/qrenderdoc/Windows/PerformanceCounterViewer.h +++ b/qrenderdoc/Windows/PerformanceCounterViewer.h @@ -50,4 +50,5 @@ public: private: Ui::PerformanceCounterViewer *ui; ICaptureContext &m_Ctx; + void CaptureCounters(); }; diff --git a/qrenderdoc/Windows/PerformanceCounterViewer.ui b/qrenderdoc/Windows/PerformanceCounterViewer.ui index 01afc89bb..4df628fea 100644 --- a/qrenderdoc/Windows/PerformanceCounterViewer.ui +++ b/qrenderdoc/Windows/PerformanceCounterViewer.ui @@ -13,42 +13,42 @@ Performance Counter viewer - - QFrame::StyledPanel - - - QFrame::Raised - + + QFrame::StyledPanel + + + QFrame::Raised + - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + - - 3 - - - QLayout::SetDefaultConstraint - - - 6 - - - 6 - + + 3 + + + QLayout::SetDefaultConstraint + + + 6 + + + 6 + @@ -59,7 +59,11 @@ - + + + false + +