]> git.cworth.org Git - apitrace/blobdiff - gui/profiledialog.cpp
Use skiplist-based FastCallSet within trace::CallSet
[apitrace] / gui / profiledialog.cpp
index 5568b54120a905518f97dc50af6e8658722adf47..a9892cf07a0f74d82391f671b5410b86eb49bf42 100644 (file)
 #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 {
+        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));
     }
 }