X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=gui%2Fprofiledialog.cpp;h=a9892cf07a0f74d82391f671b5410b86eb49bf42;hb=c8695f74ce1ee6a93dee4b3f7da5a70a64706c82;hp=5568b54120a905518f97dc50af6e8658722adf47;hpb=fc4f55a3193269f86c142219f5593dd8b8e9b3c8;p=apitrace diff --git a/gui/profiledialog.cpp b/gui/profiledialog.cpp index 5568b54..a9892cf 100644 --- a/gui/profiledialog.cpp +++ b/gui/profiledialog.cpp @@ -2,14 +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))); + + /* 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_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))); } @@ -19,64 +148,117 @@ 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); + if (profile && profile->frames.size()) { + HeatmapVerticalAxisWidget* programAxis; + FrameAxisWidget* frameAxis; + HistogramView* histogram; + HeatmapView* heatmap; + + + /* Setup data providers for Cpu graph */ + m_cpuGraph->setProfile(profile); + histogram = (HistogramView*)m_cpuGraph->view(); + frameAxis = (FrameAxisWidget*)m_cpuGraph->axis(GraphWidget::AxisTop); - ProfileTableModel* model = new ProfileTableModel(m_table); - model->setProfile(m_profile); + histogram->setDataProvider(new CallDurationDataProvider(profile, false)); + frameAxis->setDataProvider(new FrameCallDataProvider(profile)); - delete m_table->model(); - m_table->setModel(model); - m_table->resizeColumnsToContents(); - m_table->sortByColumn(2, Qt::DescendingOrder); + /* 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)); + + /* 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)); + + /* 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; } -void ProfileDialog::selectionChanged(int64_t start, int64_t end) +void ProfileDialog::graphSelectionChanged(SelectionState state) { ProfileTableModel* model = (ProfileTableModel*)m_table->model(); - model->setTimeSelection(start, end); - m_table->reset(); -} + if (!model) { + return; + } -void ProfileDialog::setVerticalScrollMax(int max) -{ - if (max <= 0) { - m_verticalScrollBar->hide(); - } else { - m_verticalScrollBar->show(); - m_verticalScrollBar->setMinimum(0); - m_verticalScrollBar->setMaximum(max); + 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); } -} + m_table->reset(); -void ProfileDialog::setHorizontalScrollMax(int max) -{ - if (max <= 0) { - m_horizontalScrollBar->hide(); - } else { - m_horizontalScrollBar->show(); - m_horizontalScrollBar->setMinimum(0); - m_horizontalScrollBar->setMaximum(max); + if (state.type == SelectionState::Vertical) { + m_table->selectRow(model->getRowIndex(state.start)); } }