blob: 4f16c58d22e61b0a70660d147775f90a276507f1 [file] [log] [blame]
#include "profiledialog.h"
#include "profiletablemodel.h"
#include <QSortFilterProxyModel>
#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 override {
return m_profile->frames.size();
}
qint64 frameStart(unsigned index) const override {
return m_profile->frames[index].calls.begin;
}
qint64 frameEnd(unsigned index) const override {
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 override {
return m_profile->frames.size();
}
qint64 frameStart(unsigned index) const override {
return m_profile->frames[index].cpuStart;
}
qint64 frameEnd(unsigned index) const override {
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);
/* 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)));
}
ProfileDialog::~ProfileDialog()
{
delete m_profile;
}
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 (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);
histogram->setDataProvider(new CallDurationDataProvider(profile, false));
frameAxis->setDataProvider(new FrameCallDataProvider(profile));
/* 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()->setSectionResizeMode(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::graphSelectionChanged(SelectionState state)
{
ProfileTableModel* model = (ProfileTableModel*)m_table->model();
if (!model) {
return;
}
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();
if (state.type == SelectionState::Vertical) {
m_table->selectRow(model->getRowIndex(state.start));
}
}
#include "profiledialog.moc"