1 #ifndef PROFILEHEATMAP_H
2 #define PROFILEHEATMAP_H
4 #include "graphing/heatmapview.h"
8 * Data providers for a heatmap based off the trace::Profile call data
11 class ProfileHeatmapRowIterator : public HeatmapRowIterator {
13 ProfileHeatmapRowIterator(const trace::Profile* profile, qint64 start, qint64 end, int steps, bool gpu, int program = -1) :
24 m_timeSelection(false),
25 m_programSelection(false)
27 m_timeWidth = m_timeEnd - m_timeStart;
32 unsigned maxIndex = m_program == -1 ? m_profile->calls.size() : m_profile->programs[m_program].calls.size();
34 if (m_index >= maxIndex) {
38 double dtds = m_timeWidth / (double)m_stepCount;
40 qint64 heatDuration = 0;
41 qint64 programHeatDuration = 0;
43 m_step += m_stepWidth;
48 /* Iterator through calls until step != lastStep */
49 for (; m_index < maxIndex; ++m_index)
51 const trace::Profile::Call* call;
53 if (m_program == -1) {
54 call = &m_profile->calls[m_index];
56 call = &m_profile->calls[ m_profile->programs[m_program].calls[m_index] ];
59 qint64 start, duration, end;
62 start = call->gpuStart;
63 duration = call->gpuDuration;
65 if (call->pixels < 0) {
69 start = call->cpuStart;
70 duration = call->cpuDuration;
73 end = start + duration;
75 if (end < m_timeStart) {
79 if (start > m_timeEnd) {
80 m_index = m_profile->calls.size();
84 double left = timeToStep(start);
85 double right = timeToStep(end);
88 int rightStep = right;
90 if (leftStep > m_step) {
94 if (m_programSelection && call->program == m_programSel) {
98 if (rightStep - leftStep > 1) {
99 m_label = QString::fromStdString(call->name);
101 m_stepWidth = rightStep - leftStep;
107 if (leftStep < m_step) {
108 qint64 rightTime = stepToTime(rightStep);
109 heatDuration += end - rightTime;
111 if (m_programSelection && call->program == m_programSel) {
112 programHeatDuration += end - rightTime;
114 } else if (leftStep == rightStep) {
115 heatDuration += duration;
117 if (m_programSelection && call->program == m_programSel) {
118 programHeatDuration += duration;
120 } else if (rightStep - leftStep == 1) {
121 qint64 rightTime = stepToTime(rightStep);
122 heatDuration += rightTime - start;
124 if (m_programSelection && call->program == m_programSel) {
125 programHeatDuration += rightTime - start;
132 m_heat = heatDuration / dtds;
133 m_programHeat = programHeatDuration / dtds;
135 if (m_timeSelection) {
136 qint64 time = stepToTime(m_step);
138 if (time >= m_timeSelStart && time <= m_timeSelEnd) {
143 if (m_programSelection && (m_program == m_programSel || (m_selected && m_stepWidth > 1))) {
147 if (m_programHeat > 0) {
154 virtual bool isGpu() const
159 virtual float heat() const
164 virtual float selectedHeat() const
166 return m_programHeat;
169 virtual int step() const
174 virtual int width() const
179 virtual QString label() const
184 void setProgramSelection(int program)
186 m_programSelection = true;
187 m_programSel = program;
190 void setTimeSelection(qint64 start, qint64 end)
192 m_timeSelection = true;
193 m_timeSelStart = start;
198 double timeToStep(qint64 time) const
207 qint64 stepToTime(int pos) const
217 const trace::Profile* m_profile;
238 bool m_timeSelection;
239 qint64 m_timeSelStart;
242 bool m_programSelection;
248 class ProfileHeatmapDataProvider : public HeatmapDataProvider {
257 ProfileHeatmapDataProvider(trace::Profile* profile) :
259 m_selectionState(NULL)
264 virtual qint64 start() const
266 return m_profile->frames.front().cpuStart;
269 virtual qint64 end() const
271 return m_profile->frames.back().cpuStart + m_profile->frames.back().cpuDuration;
274 virtual unsigned dataRows() const
276 return m_rowPrograms.size();
279 virtual QString dataLabel(unsigned row) const
281 if (row >= m_rowPrograms.size()) {
284 return QString("%1").arg(m_rowPrograms[row]);
288 virtual qint64 dataRowAt(unsigned row) const
290 if (row >= m_rowPrograms.size()) {
293 return m_rowPrograms[row];
297 virtual HeatmapRowIterator* dataRowIterator(int row, qint64 start, qint64 end, int steps) const
299 ProfileHeatmapRowIterator* itr = new ProfileHeatmapRowIterator(m_profile, start, end, steps, true, m_rowPrograms[row]);
301 if (m_selectionState) {
302 if (m_selectionState->type == SelectionState::Horizontal) {
303 itr->setTimeSelection(m_selectionState->start, m_selectionState->end);
304 } else if (m_selectionState->type == SelectionState::Vertical) {
305 itr->setProgramSelection(m_selectionState->start);
312 virtual unsigned headerRows() const
317 virtual qint64 headerRowAt(unsigned row) const
322 virtual QString headerLabel(unsigned row) const
326 } else if (row == 1) {
333 virtual HeatmapRowIterator* headerRowIterator(int row, qint64 start, qint64 end, int steps) const
335 ProfileHeatmapRowIterator* itr = new ProfileHeatmapRowIterator(m_profile, start, end, steps, row != 0);
337 if (m_selectionState) {
338 if (m_selectionState->type == SelectionState::Horizontal) {
339 itr->setTimeSelection(m_selectionState->start, m_selectionState->end);
340 } else if (m_selectionState->type == SelectionState::Vertical) {
341 itr->setProgramSelection(m_selectionState->start);
348 virtual qint64 dataItemAt(unsigned row, qint64 time) const
350 if (row >= m_rowPrograms.size()) {
354 unsigned program = m_rowPrograms[row];
356 std::vector<unsigned>::const_iterator item =
357 Profiling::binarySearchTimespanIndexed
358 (m_profile->calls, m_profile->programs[program].calls.begin(), m_profile->programs[program].calls.end(), time);
360 if (item == m_profile->programs[program].calls.end()) {
367 virtual qint64 headerItemAt(unsigned row, qint64 time) const
369 if (row >= m_rowPrograms.size()) {
375 std::vector<trace::Profile::Call>::const_iterator item =
376 Profiling::binarySearchTimespan<trace::Profile::Call,
377 &trace::Profile::Call::cpuStart,
378 &trace::Profile::Call::cpuDuration>
379 (m_profile->calls.begin(), m_profile->calls.end(), time);
381 if (item != m_profile->calls.end()) {
382 return item - m_profile->calls.begin();
384 } else if (row == 1) {
386 for (unsigned i = 0; i < m_rowPrograms.size(); ++i) {
387 qint64 index = dataItemAt(i, time);
398 virtual void itemDoubleClicked(qint64 index) const
400 if (index < 0 || index >= m_profile->calls.size()) {
404 const trace::Profile::Call& call = m_profile->calls[index];
405 Profiling::jumpToCall(call.no);
408 virtual QString itemTooltip(qint64 index) const
410 if (index >= m_profile->calls.size()) {
414 const trace::Profile::Call& call = m_profile->calls[index];
417 text = QString::fromStdString(call.name);
419 text += QString("\nCall: %1").arg(call.no);
420 text += QString("\nCPU Start: %1").arg(Profiling::getTimeString(call.cpuStart));
421 text += QString("\nCPU Duration: %1").arg(Profiling::getTimeString(call.cpuDuration));
423 if (call.pixels >= 0) {
424 text += QString("\nGPU Start: %1").arg(Profiling::getTimeString(call.gpuStart));
425 text += QString("\nGPU Duration: %1").arg(Profiling::getTimeString(call.gpuDuration));
426 text += QString("\nPixels Drawn: %1").arg(QLocale::system().toString((qlonglong)call.pixels));
432 virtual void setSelectionState(SelectionState* state)
434 m_selectionState = state;
440 typedef QPair<quint64, unsigned> Pair;
441 std::vector<Pair> gpu;
443 /* Map shader to visible row */
444 for (std::vector<trace::Profile::Program>::const_iterator itr = m_profile->programs.begin(); itr != m_profile->programs.end(); ++itr) {
445 const trace::Profile::Program& program = *itr;
446 unsigned no = itr - m_profile->programs.begin();
448 if (program.gpuTotal > 0) {
449 gpu.push_back(Pair(program.gpuTotal, no));
453 /* Sort the shaders by most used gpu */
456 /* Create row order */
457 m_rowPrograms.clear();
459 for (std::vector<Pair>::const_reverse_iterator itr = gpu.rbegin(); itr != gpu.rend(); ++itr) {
460 m_rowPrograms.push_back(itr->second);
465 trace::Profile* m_profile;
466 std::vector<int> m_rowPrograms;
467 SelectionState* m_selectionState;