blob: 11a0d0c10901e299b271dfabad75e4948fb0c5f7 [file] [log] [blame]
James Bentonfc4f55a2012-08-08 17:09:07 +01001#include "profiletablemodel.h"
James Benton902626c2012-08-22 12:18:09 +01002#include "profiledialog.h"
James Benton0b65a2b2012-09-07 18:38:15 +01003#include "profiling.h"
James Benton902626c2012-08-22 12:18:09 +01004
5#include <QLocale>
James Bentonfc4f55a2012-08-08 17:09:07 +01006
James Benton4c4896f2012-08-22 12:11:37 +01007typedef trace::Profile::Call Call;
James Bentonfc4f55a2012-08-08 17:09:07 +01008typedef trace::Profile::Frame Frame;
James Benton56ad11c2012-08-16 13:44:19 +01009typedef trace::Profile::Program Program;
James Bentonfc4f55a2012-08-08 17:09:07 +010010
11enum {
12 COLUMN_PROGRAM,
13 COLUMN_USAGES,
14 COLUMN_GPU_TIME,
15 COLUMN_CPU_TIME,
16 COLUMN_PIXELS_DRAWN,
17 COLUMN_GPU_AVERAGE,
18 COLUMN_CPU_AVERAGE,
19 COLUMN_PIXELS_AVERAGE,
20 MAX_COLUMN
21};
22
23static QString columnNames[] = {
24 QString("Program"),
25 QString("Calls"),
26 QString("Total GPU Time"),
27 QString("Total CPU Time"),
28 QString("Total Pixels Drawn"),
29 QString("Avg GPU Time"),
30 QString("Avg CPU Time"),
31 QString("Avg Pixels Drawn")
32};
33
34ProfileTableModel::ProfileTableModel(QObject *parent)
35 : QAbstractTableModel(parent),
36 m_profile(0),
37 m_sortColumn(COLUMN_GPU_TIME),
38 m_sortOrder(Qt::DescendingOrder)
39{
40}
41
42
43void ProfileTableModel::setProfile(trace::Profile* profile)
44{
45 m_profile = profile;
James Benton56ad11c2012-08-16 13:44:19 +010046 m_timeMin = m_profile->frames.front().cpuStart;
47 m_timeMax = m_profile->frames.back().cpuStart + m_profile->frames.back().cpuDuration;
James Bentonfc4f55a2012-08-08 17:09:07 +010048 updateModel();
49}
50
51
James Bentonb70a86a2012-08-28 18:41:43 +010052/**
53 * Set selection to nothing
54 */
55void ProfileTableModel::selectNone()
56{
57 m_timeMin = m_timeMax = 0;
58 updateModel();
59 sort(m_sortColumn, m_sortOrder);
60}
61
62
63/**
64 * Set selection to program
65 */
66void ProfileTableModel::selectProgram(unsigned /*program*/)
67{
68 /* We have no program based selection for table */
69 selectNone();
70}
71
72
73/**
74 * Set selection to a period of time
75 */
76void ProfileTableModel::selectTime(int64_t start, int64_t end)
James Bentonfc4f55a2012-08-08 17:09:07 +010077{
78 m_timeMin = start;
79 m_timeMax = end;
James Bentonb70a86a2012-08-28 18:41:43 +010080
James Bentonfc4f55a2012-08-08 17:09:07 +010081 updateModel();
82 sort(m_sortColumn, m_sortOrder);
83}
84
85
86/**
87 * Creates the row data from trace profile
88 */
89void ProfileTableModel::updateModel()
90{
91 if (m_timeMin == m_timeMax) {
James Benton56ad11c2012-08-16 13:44:19 +010092 m_timeMin = m_profile->frames.front().cpuStart;
93 m_timeMax = m_profile->frames.back().cpuStart + m_profile->frames.back().cpuDuration;
James Bentonfc4f55a2012-08-08 17:09:07 +010094 }
95
96 for (QList<ProfileTableRow>::iterator itr = m_rowData.begin(); itr != m_rowData.end(); ++itr) {
97 ProfileTableRow& row = *itr;
98
99 row.uses = 0;
100 row.pixels = 0;
101 row.gpuTime = 0;
102 row.cpuTime = 0;
103 row.longestCpu = NULL;
104 row.longestGpu = NULL;
105 row.longestPixel = NULL;
106 }
107
James Benton56ad11c2012-08-16 13:44:19 +0100108 for (std::vector<Program>::const_iterator itr = m_profile->programs.begin(); itr != m_profile->programs.end(); ++itr) {
James Benton4c4896f2012-08-22 12:11:37 +0100109 ProfileTableRow* row = NULL;
James Benton56ad11c2012-08-16 13:44:19 +0100110 const Program& program = *itr;
James Bentonfc4f55a2012-08-08 17:09:07 +0100111
James Benton4c4896f2012-08-22 12:11:37 +0100112 for (std::vector<unsigned>::const_iterator jtr = program.calls.begin(); jtr != program.calls.end(); ++jtr) {
113 const Call& call = m_profile->calls[*jtr];
James Bentonfc4f55a2012-08-08 17:09:07 +0100114
James Benton56ad11c2012-08-16 13:44:19 +0100115 if (call.cpuStart > m_timeMax) {
James Bentonfc4f55a2012-08-08 17:09:07 +0100116 break;
117 }
118
James Benton56ad11c2012-08-16 13:44:19 +0100119 if (call.cpuStart + call.cpuDuration < m_timeMin) {
James Bentonfc4f55a2012-08-08 17:09:07 +0100120 continue;
121 }
122
James Benton4c4896f2012-08-22 12:11:37 +0100123 if (!row) {
124 row = getRow(itr - m_profile->programs.begin());
125 }
126
James Bentonfc4f55a2012-08-08 17:09:07 +0100127 row->uses++;
James Benton56ad11c2012-08-16 13:44:19 +0100128 row->pixels += call.pixels;
James Bentonfc4f55a2012-08-08 17:09:07 +0100129 row->gpuTime += call.gpuDuration;
130 row->cpuTime += call.cpuDuration;
James Bentonfc4f55a2012-08-08 17:09:07 +0100131
132 if (!row->longestGpu || row->longestGpu->gpuDuration < call.gpuDuration) {
133 row->longestGpu = &call;
134 }
135
136 if (!row->longestCpu || row->longestCpu->cpuDuration < call.cpuDuration) {
137 row->longestCpu = &call;
138 }
139
140 if (!row->longestPixel || row->longestPixel->pixels < call.pixels) {
141 row->longestPixel = &call;
142 }
143 }
144 }
145}
146
147
148/**
149 * Get the appropriate call associated with an item in the table
150 */
James Benton4c4896f2012-08-22 12:11:37 +0100151const trace::Profile::Call *ProfileTableModel::getJumpCall(const QModelIndex & index) const {
James Bentonfc4f55a2012-08-08 17:09:07 +0100152 const ProfileTableRow& row = m_rowData[index.row()];
153
154 switch(index.column()) {
155 case COLUMN_GPU_TIME:
156 case COLUMN_GPU_AVERAGE:
157 return row.longestGpu;
158 case COLUMN_CPU_TIME:
159 case COLUMN_CPU_AVERAGE:
160 return row.longestCpu;
161 case COLUMN_PIXELS_DRAWN:
162 case COLUMN_PIXELS_AVERAGE:
163 return row.longestPixel;
164 }
165
166 return NULL;
167}
168
169
James Bentonb70a86a2012-08-28 18:41:43 +0100170/**
171 * Get the shader program associated with an item in the table
172 */
173unsigned ProfileTableModel::getProgram(const QModelIndex & index) const
174{
175 const ProfileTableRow& row = m_rowData[index.row()];
176 return row.program;
177}
178
179
180/**
181 * Get the row index for a shader program
182 */
183int ProfileTableModel::getRowIndex(unsigned program) const
184{
185 for (int i = 0; i < m_rowData.size(); ++i) {
186 if (m_rowData[i].program == program)
187 return i;
188 }
189
190 return -1;
191}
192
193
194/**
195 * Get the row data for a shader program
196 */
James Bentonfc4f55a2012-08-08 17:09:07 +0100197ProfileTableRow* ProfileTableModel::getRow(unsigned program) {
198 for (QList<ProfileTableRow>::iterator itr = m_rowData.begin(); itr != m_rowData.end(); ++itr) {
199 if (itr->program == program)
200 return &*itr;
201 }
202
James Benton56ad11c2012-08-16 13:44:19 +0100203 m_rowData.append(ProfileTableRow(program));
204 return &m_rowData.back();
James Bentonfc4f55a2012-08-08 17:09:07 +0100205}
206
207
208int ProfileTableModel::rowCount(const QModelIndex & parent) const
209{
210 if (!parent.isValid()) {
211 return m_rowData.size();
212 } else {
213 return 0;
214 }
215}
216
217
218int ProfileTableModel::columnCount(const QModelIndex & /*parent*/) const
219{
220 return MAX_COLUMN;
221}
222
223
224QVariant ProfileTableModel::data(const QModelIndex &index, int role) const
225{
226 if (!index.isValid()) {
227 return QVariant();
228 }
229
230 if (role == Qt::DisplayRole) {
231 const ProfileTableRow& row = m_rowData[index.row()];
232
233 switch(index.column()) {
234 case COLUMN_PROGRAM:
235 return row.program;
236 case COLUMN_USAGES:
James Benton902626c2012-08-22 12:18:09 +0100237 return QLocale::system().toString(row.uses);
James Bentonfc4f55a2012-08-08 17:09:07 +0100238 case COLUMN_GPU_TIME:
James Benton0b65a2b2012-09-07 18:38:15 +0100239 return Profiling::getTimeString(row.gpuTime);
James Bentonfc4f55a2012-08-08 17:09:07 +0100240 case COLUMN_CPU_TIME:
James Benton0b65a2b2012-09-07 18:38:15 +0100241 return Profiling::getTimeString(row.cpuTime);
James Bentonfc4f55a2012-08-08 17:09:07 +0100242 case COLUMN_PIXELS_DRAWN:
James Benton902626c2012-08-22 12:18:09 +0100243 return QLocale::system().toString((qlonglong)row.pixels);
James Bentonfc4f55a2012-08-08 17:09:07 +0100244 case COLUMN_GPU_AVERAGE:
James Benton0b65a2b2012-09-07 18:38:15 +0100245 return Profiling::getTimeString((row.uses <= 0) ? 0 : (row.gpuTime / row.uses));
James Bentonfc4f55a2012-08-08 17:09:07 +0100246 case COLUMN_CPU_AVERAGE:
James Benton0b65a2b2012-09-07 18:38:15 +0100247 return Profiling::getTimeString((row.uses <= 0) ? 0 : (row.cpuTime / row.uses));
James Bentonfc4f55a2012-08-08 17:09:07 +0100248 case COLUMN_PIXELS_AVERAGE:
James Benton902626c2012-08-22 12:18:09 +0100249 return QLocale::system().toString((row.uses <= 0) ? 0 : (row.pixels / row.uses));
James Bentonfc4f55a2012-08-08 17:09:07 +0100250 }
251 } else if (role == Qt::TextAlignmentRole) {
252 return Qt::AlignRight;
253 }
254
255 return QVariant();
256}
257
258
259QVariant ProfileTableModel::headerData(int section, Qt::Orientation orientation, int role) const
260{
261 if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
262 if (section >= 0 && section < MAX_COLUMN) {
263 return columnNames[section];
264 }
265 }
266
267 return QVariant();
268}
269
270
271class ProgramSorter {
272public:
273 ProgramSorter(int column, Qt::SortOrder order)
274 : mSortColumn(column),
275 mSortOrder(order)
276 {
277 }
278
279 bool operator()(const ProfileTableRow &p1, const ProfileTableRow &p2) const
280 {
281 bool result = true;
282
283 switch(mSortColumn) {
284 case COLUMN_PROGRAM:
285 result = p1.program < p2.program;
286 break;
287 case COLUMN_USAGES:
288 result = p1.uses < p2.uses;
289 break;
290 case COLUMN_GPU_TIME:
291 result = p1.gpuTime < p2.gpuTime;
292 break;
293 case COLUMN_CPU_TIME:
294 result = p1.cpuTime < p2.cpuTime;
295 break;
296 case COLUMN_PIXELS_DRAWN:
297 result = p1.pixels < p2.pixels;
298 break;
299 case COLUMN_GPU_AVERAGE:
James Benton08717052012-08-08 17:43:52 +0100300 result = ((p1.uses <= 0) ? 0 : (p1.gpuTime / p1.uses)) < ((p2.uses <= 0) ? 0 : (p2.gpuTime / p2.uses));
James Bentonfc4f55a2012-08-08 17:09:07 +0100301 break;
302 case COLUMN_CPU_AVERAGE:
James Benton08717052012-08-08 17:43:52 +0100303 result = ((p1.uses <= 0) ? 0 : (p1.cpuTime / p1.uses)) < ((p2.uses <= 0) ? 0 : (p2.cpuTime / p2.uses));
James Bentonfc4f55a2012-08-08 17:09:07 +0100304 break;
305 case COLUMN_PIXELS_AVERAGE:
James Benton08717052012-08-08 17:43:52 +0100306 result = ((p1.uses <= 0) ? 0 : (p1.pixels / p1.uses)) < ((p2.uses <= 0) ? 0 : (p2.pixels / p2.uses));
James Bentonfc4f55a2012-08-08 17:09:07 +0100307 break;
308 }
309
310 if (mSortOrder == Qt::DescendingOrder) {
311 return !result;
312 } else {
313 return result;
314 }
315 }
316
317private:
318 int mSortColumn;
319 Qt::SortOrder mSortOrder;
320};
321
322
323void ProfileTableModel::sort(int column, Qt::SortOrder order) {
324 m_sortColumn = column;
325 m_sortOrder = order;
326 qSort(m_rowData.begin(), m_rowData.end(), ProgramSorter(column, order));
327 emit dataChanged(createIndex(0, 0), createIndex(m_rowData.size(), MAX_COLUMN));
328}
329
330
331#include "profiletablemodel.moc"