X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=gui%2Fprofiledialog.cpp;h=a9892cf07a0f74d82391f671b5410b86eb49bf42;hb=4b3c99d04556d642a25b032eca65338ed99bcac7;hp=146e26a25d42bea544395089c3504a7fe56b9642;hpb=418a32e9905d0253571bfc33f2859c8fef34039d;p=apitrace diff --git a/gui/profiledialog.cpp b/gui/profiledialog.cpp index 146e26a..a9892cf 100644 --- a/gui/profiledialog.cpp +++ b/gui/profiledialog.cpp @@ -2,20 +2,143 @@ #include "profiletablemodel.h" #include +#include "graphing/histogramview.h" +#include "graphing/timeaxiswidget.h" +#include "graphing/frameaxiswidget.h" +#include "graphing/heatmapverticalaxiswidget.h" +#include "profileheatmap.h" + +/* Handy function to allow selection of a call in main window */ +ProfileDialog* g_profileDialog = 0; + +void Profiling::jumpToCall(int index) +{ + if (g_profileDialog) { + g_profileDialog->showCall(index); + } +} + +/* Provides frame numbers based off call index */ +class FrameCallDataProvider : public FrameDataProvider { +public: + FrameCallDataProvider(const trace::Profile* profile) + { + m_profile = profile; + } + + unsigned size() const { + return m_profile->frames.size(); + } + + qint64 frameStart(unsigned index) const { + return m_profile->frames[index].calls.begin; + } + + qint64 frameEnd(unsigned index) const { + return m_profile->frames[index].calls.end; + } + +private: + const trace::Profile* m_profile; +}; + +/* Provides frame numbers based off time */ +class FrameTimeDataProvider : public FrameDataProvider { +public: + FrameTimeDataProvider(const trace::Profile* profile) + { + m_profile = profile; + } + + unsigned size() const { + return m_profile->frames.size(); + } + + qint64 frameStart(unsigned index) const { + return m_profile->frames[index].cpuStart; + } + + qint64 frameEnd(unsigned index) const { + return m_profile->frames[index].cpuStart + m_profile->frames[index].cpuDuration; + } + +private: + const trace::Profile* m_profile; +}; + ProfileDialog::ProfileDialog(QWidget *parent) : QDialog(parent), m_profile(0) { setupUi(this); + g_profileDialog = this; + + /* Gradients for call duration histograms */ + QLinearGradient cpuGradient; + cpuGradient.setColorAt(0.9, QColor(0, 0, 210)); + cpuGradient.setColorAt(0.0, QColor(130, 130, 255)); + + QLinearGradient gpuGradient; + gpuGradient.setColorAt(0.9, QColor(210, 0, 0)); + gpuGradient.setColorAt(0.0, QColor(255, 130, 130)); + + + /* Setup heatmap timeline */ + m_timeline->setLabel(new GraphLabelWidget("Frames ", m_timeline)); + m_timeline->label()->setFlags(Qt::AlignVCenter | Qt::AlignRight); + + m_timeline->setView(new HeatmapView(m_timeline)); + + m_timeline->setAxis(GraphWidget::AxisTop, new FrameAxisWidget(m_timeline)); + m_timeline->setAxis(GraphWidget::AxisLeft, new HeatmapVerticalAxisWidget(m_timeline)); + m_timeline->axis(GraphWidget::AxisLeft)->resize(80, 0); + + m_timeline->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); + m_timeline->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + + + /* Setup Cpu call duration histogram */ + m_cpuGraph->setLabel(new GraphLabelWidget("CPU", m_cpuGraph)); + + m_cpuGraph->setAxis(GraphWidget::AxisTop, new FrameAxisWidget(m_cpuGraph)); + m_cpuGraph->setAxis(GraphWidget::AxisLeft, new TimeAxisWidget(m_cpuGraph)); + m_cpuGraph->axis(GraphWidget::AxisLeft)->resize(80, 0); + + HistogramView* cpuView = new HistogramView(m_cpuGraph); + cpuView->setSelectedGradient(cpuGradient); + m_cpuGraph->setView(cpuView); + + + /* Setup Gpu call duration histogram */ + m_gpuGraph->setLabel(new GraphLabelWidget("GPU", m_gpuGraph)); + + m_gpuGraph->setAxis(GraphWidget::AxisTop, new FrameAxisWidget(m_gpuGraph)); + m_gpuGraph->setAxis(GraphWidget::AxisLeft, new TimeAxisWidget(m_gpuGraph)); + m_gpuGraph->axis(GraphWidget::AxisLeft)->resize(80, 0); + + HistogramView* gpuView = new HistogramView(m_gpuGraph); + gpuView->setSelectedGradient(gpuGradient); + m_gpuGraph->setView(gpuView); - connect(m_timeline, SIGNAL(jumpToCall(int)), SIGNAL(jumpToCall(int))); - connect(m_timeline, SIGNAL(selectionChanged(int64_t,int64_t)), SLOT(selectionChanged(int64_t,int64_t))); - connect(m_gpuGraph, SIGNAL(jumpToCall(int)), SIGNAL(jumpToCall(int))); - connect(m_cpuGraph, SIGNAL(jumpToCall(int)), SIGNAL(jumpToCall(int))); + /* Synchronise selections */ + connect(m_timeline, SIGNAL(selectionChanged(SelectionState)), m_cpuGraph, SLOT(setSelection(SelectionState))); + connect(m_timeline, SIGNAL(selectionChanged(SelectionState)), m_gpuGraph, SLOT(setSelection(SelectionState))); - connect(m_gpuGraph, SIGNAL(viewChanged(int,int)), m_cpuGraph, SLOT(changeView(int,int))); - connect(m_cpuGraph, SIGNAL(viewChanged(int,int)), m_gpuGraph, SLOT(changeView(int,int))); + connect(m_cpuGraph, SIGNAL(selectionChanged(SelectionState)), m_timeline, SLOT(setSelection(SelectionState))); + connect(m_cpuGraph, SIGNAL(selectionChanged(SelectionState)), m_gpuGraph, SLOT(setSelection(SelectionState))); + + connect(m_gpuGraph, SIGNAL(selectionChanged(SelectionState)), m_timeline, SLOT(setSelection(SelectionState))); + connect(m_gpuGraph, SIGNAL(selectionChanged(SelectionState)), m_cpuGraph, SLOT(setSelection(SelectionState))); + + connect(m_timeline, SIGNAL(selectionChanged(SelectionState)), this, SLOT(graphSelectionChanged(SelectionState))); + connect(m_cpuGraph, SIGNAL(selectionChanged(SelectionState)), this, SLOT(graphSelectionChanged(SelectionState))); + connect(m_gpuGraph, SIGNAL(selectionChanged(SelectionState)), this, SLOT(graphSelectionChanged(SelectionState))); + + + /* Synchronise views between cpuGraph and gpuGraph */ + connect(m_cpuGraph, SIGNAL(horizontalViewChanged(qint64,qint64)), m_gpuGraph, SLOT(setHorizontalView(qint64,qint64))); + connect(m_gpuGraph, SIGNAL(horizontalViewChanged(qint64,qint64)), m_cpuGraph, SLOT(setHorizontalView(qint64,qint64))); } @@ -25,115 +148,118 @@ ProfileDialog::~ProfileDialog() } +void ProfileDialog::showCall(int call) +{ + emit jumpToCall(call); +} + + void ProfileDialog::tableDoubleClicked(const QModelIndex& index) { ProfileTableModel* model = (ProfileTableModel*)m_table->model(); + + if (!model) { + return; + } + const trace::Profile::Call* call = model->getJumpCall(index); if (call) { emit jumpToCall(call->no); + } else { + unsigned program = model->getProgram(index); + + SelectionState state; + state.type = SelectionState::Vertical; + state.end = state.start = program; + + m_timeline->setSelection(state); + m_cpuGraph->setSelection(state); + m_gpuGraph->setSelection(state); } } void ProfileDialog::setProfile(trace::Profile* profile) { - if (m_profile) { - delete m_profile; - } - m_profile = profile; - m_timeline->setProfile(m_profile); - m_gpuGraph->setProfile(m_profile, GraphGpu); - m_cpuGraph->setProfile(m_profile, GraphCpu); + if (profile && profile->frames.size()) { + HeatmapVerticalAxisWidget* programAxis; + FrameAxisWidget* frameAxis; + HistogramView* histogram; + HeatmapView* heatmap; - ProfileTableModel* model = new ProfileTableModel(m_table); - model->setProfile(m_profile); - delete m_table->model(); - m_table->setModel(model); - m_table->resizeColumnsToContents(); - m_table->sortByColumn(2, Qt::DescendingOrder); -} + /* Setup data providers for Cpu graph */ + m_cpuGraph->setProfile(profile); + histogram = (HistogramView*)m_cpuGraph->view(); + frameAxis = (FrameAxisWidget*)m_cpuGraph->axis(GraphWidget::AxisTop); + histogram->setDataProvider(new CallDurationDataProvider(profile, false)); + frameAxis->setDataProvider(new FrameCallDataProvider(profile)); -void ProfileDialog::selectionChanged(int64_t start, int64_t end) -{ - ProfileTableModel* model = (ProfileTableModel*)m_table->model(); - model->setTimeSelection(start, end); - m_table->reset(); -} + /* Setup data provider for Gpu graph */ + m_gpuGraph->setProfile(profile); + histogram = (HistogramView*)m_gpuGraph->view(); + frameAxis = (FrameAxisWidget*)m_gpuGraph->axis(GraphWidget::AxisTop); + histogram->setDataProvider(new CallDurationDataProvider(profile, true)); + frameAxis->setDataProvider(new FrameCallDataProvider(profile)); -void ProfileDialog::setVerticalScrollMax(int max) -{ - if (max <= 0) { - m_verticalScrollBar->hide(); - } else { - m_verticalScrollBar->show(); - m_verticalScrollBar->setMinimum(0); - m_verticalScrollBar->setMaximum(max); - } -} + /* Setup data provider for heatmap timeline */ + heatmap = (HeatmapView*)m_timeline->view(); + frameAxis = (FrameAxisWidget*)m_timeline->axis(GraphWidget::AxisTop); + programAxis = (HeatmapVerticalAxisWidget*)m_timeline->axis(GraphWidget::AxisLeft); + heatmap->setDataProvider(new ProfileHeatmapDataProvider(profile)); + frameAxis->setDataProvider(new FrameTimeDataProvider(profile)); + programAxis->setDataProvider(new ProfileHeatmapDataProvider(profile)); -void ProfileDialog::setHorizontalScrollMax(int max) -{ - if (max <= 0) { - m_horizontalScrollBar->hide(); - } else { - m_horizontalScrollBar->show(); - m_horizontalScrollBar->setMinimum(0); - m_horizontalScrollBar->setMaximum(max); + /* Setup data model for table view */ + ProfileTableModel* model = new ProfileTableModel(m_table); + model->setProfile(profile); + + delete m_table->model(); + m_table->setModel(model); + m_table->update(QModelIndex()); + m_table->sortByColumn(2, Qt::DescendingOrder); + m_table->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents); + m_table->resizeColumnsToContents(); + + /* Reset selection */ + SelectionState emptySelection; + emptySelection.type = SelectionState::None; + m_cpuGraph->setSelection(emptySelection); + m_gpuGraph->setSelection(emptySelection); + m_timeline->setSelection(emptySelection); } + + delete m_profile; + m_profile = profile; } -/** - * Convert a CPU / GPU time to a textual representation. - * This includes automatic unit selection. - */ -QString getTimeString(int64_t time, int64_t unitTime) +void ProfileDialog::graphSelectionChanged(SelectionState state) { - QString text; - QString unit = " ns"; - double unitScale = 1; + ProfileTableModel* model = (ProfileTableModel*)m_table->model(); - if (unitTime == 0) { - unitTime = time; + if (!model) { + return; } - if (unitTime >= 60e9) { - int64_t mins = time / 60e9; - text += QString("%1 m ").arg(mins); - - time -= mins * 60e9; - unit = " s"; - unitScale = 1e9; - } else if (unitTime >= 1e9) { - unit = " s"; - unitScale = 1e9; - } else if (unitTime >= 1e6) { - unit = " ms"; - unitScale = 1e6; - } else if (unitTime >= 1e3) { - unit = QString::fromUtf8(" µs"); - unitScale = 1e3; + if (state.type == SelectionState::None) { + model->selectNone(); + } else if (state.type == SelectionState::Horizontal) { + model->selectTime(state.start, state.end); + } else if (state.type == SelectionState::Vertical) { + model->selectProgram(state.start); } - /* 3 decimal places */ - text += QString("%1").arg(time / unitScale, 0, 'f', 3); - - /* Remove trailing 0 */ - while(text.endsWith('0')) - text.truncate(text.length() - 1); - - /* Remove trailing decimal point */ - if (text.endsWith(QLocale::system().decimalPoint())) - text.truncate(text.length() - 1); + m_table->reset(); - return text + unit; + if (state.type == SelectionState::Vertical) { + m_table->selectRow(model->getRowIndex(state.start)); + } } - #include "profiledialog.moc"