blob: 8da07e02e7a8aca7ffe8a842df0aefefbb704a32 [file] [log] [blame]
James Bentonfc4f55a2012-08-08 17:09:07 +01001#include "profiletablemodel.h"
2
3typedef trace::Profile::Call Call;
4typedef trace::Profile::Frame Frame;
5
6enum {
7 COLUMN_PROGRAM,
8 COLUMN_USAGES,
9 COLUMN_GPU_TIME,
10 COLUMN_CPU_TIME,
11 COLUMN_PIXELS_DRAWN,
12 COLUMN_GPU_AVERAGE,
13 COLUMN_CPU_AVERAGE,
14 COLUMN_PIXELS_AVERAGE,
15 MAX_COLUMN
16};
17
18static QString columnNames[] = {
19 QString("Program"),
20 QString("Calls"),
21 QString("Total GPU Time"),
22 QString("Total CPU Time"),
23 QString("Total Pixels Drawn"),
24 QString("Avg GPU Time"),
25 QString("Avg CPU Time"),
26 QString("Avg Pixels Drawn")
27};
28
29ProfileTableModel::ProfileTableModel(QObject *parent)
30 : QAbstractTableModel(parent),
31 m_profile(0),
32 m_sortColumn(COLUMN_GPU_TIME),
33 m_sortOrder(Qt::DescendingOrder)
34{
35}
36
37
38void ProfileTableModel::setProfile(trace::Profile* profile)
39{
40 m_profile = profile;
41 m_timeMin = m_profile->frames.front().gpuStart;
42 m_timeMax = m_profile->frames.back().gpuStart + m_profile->frames.back().gpuDuration;
43 updateModel();
44}
45
46
47void ProfileTableModel::setTimeSelection(int64_t start, int64_t end)
48{
49 m_timeMin = start;
50 m_timeMax = end;
51 updateModel();
52 sort(m_sortColumn, m_sortOrder);
53}
54
55
56/**
57 * Creates the row data from trace profile
58 */
59void ProfileTableModel::updateModel()
60{
61 if (m_timeMin == m_timeMax) {
62 m_timeMin = m_profile->frames.front().gpuStart;
63 m_timeMax = m_profile->frames.back().gpuStart + m_profile->frames.back().gpuDuration;
64 }
65
66 for (QList<ProfileTableRow>::iterator itr = m_rowData.begin(); itr != m_rowData.end(); ++itr) {
67 ProfileTableRow& row = *itr;
68
69 row.uses = 0;
70 row.pixels = 0;
71 row.gpuTime = 0;
72 row.cpuTime = 0;
73 row.longestCpu = NULL;
74 row.longestGpu = NULL;
75 row.longestPixel = NULL;
76 }
77
78 for (Frame::const_iterator itr = m_profile->frames.begin(); itr != m_profile->frames.end(); ++itr) {
79 const Frame& frame = *itr;
80
81 if (frame.gpuStart > m_timeMax) {
82 break;
83 }
84
85 if ((frame.gpuStart + frame.gpuDuration) < m_timeMin) {
86 continue;
87 }
88
89 for (Call::const_iterator jtr = frame.calls.begin(); jtr != frame.calls.end(); ++jtr) {
90 const Call& call = *jtr;
91
92 if (call.gpuStart > m_timeMax) {
93 break;
94 }
95
96 if ((call.gpuStart + call.gpuDuration) < m_timeMin) {
97 continue;
98 }
99
100 ProfileTableRow* row = getRow(call.program);
101 if (!row) {
102 m_rowData.append(ProfileTableRow());
103 row = &m_rowData.back();
104 }
105
106 row->uses++;
107 row->program = call.program;
108 row->gpuTime += call.gpuDuration;
109 row->cpuTime += call.cpuDuration;
110 row->pixels += call.pixels;
111
112 if (!row->longestGpu || row->longestGpu->gpuDuration < call.gpuDuration) {
113 row->longestGpu = &call;
114 }
115
116 if (!row->longestCpu || row->longestCpu->cpuDuration < call.cpuDuration) {
117 row->longestCpu = &call;
118 }
119
120 if (!row->longestPixel || row->longestPixel->pixels < call.pixels) {
121 row->longestPixel = &call;
122 }
123 }
124 }
125}
126
127
128/**
129 * Get the appropriate call associated with an item in the table
130 */
131const Call* ProfileTableModel::getJumpCall(const QModelIndex & index) const {
132 const ProfileTableRow& row = m_rowData[index.row()];
133
134 switch(index.column()) {
135 case COLUMN_GPU_TIME:
136 case COLUMN_GPU_AVERAGE:
137 return row.longestGpu;
138 case COLUMN_CPU_TIME:
139 case COLUMN_CPU_AVERAGE:
140 return row.longestCpu;
141 case COLUMN_PIXELS_DRAWN:
142 case COLUMN_PIXELS_AVERAGE:
143 return row.longestPixel;
144 }
145
146 return NULL;
147}
148
149
150ProfileTableRow* ProfileTableModel::getRow(unsigned program) {
151 for (QList<ProfileTableRow>::iterator itr = m_rowData.begin(); itr != m_rowData.end(); ++itr) {
152 if (itr->program == program)
153 return &*itr;
154 }
155
156 return NULL;
157}
158
159
160int ProfileTableModel::rowCount(const QModelIndex & parent) const
161{
162 if (!parent.isValid()) {
163 return m_rowData.size();
164 } else {
165 return 0;
166 }
167}
168
169
170int ProfileTableModel::columnCount(const QModelIndex & /*parent*/) const
171{
172 return MAX_COLUMN;
173}
174
175
176QVariant ProfileTableModel::data(const QModelIndex &index, int role) const
177{
178 if (!index.isValid()) {
179 return QVariant();
180 }
181
182 if (role == Qt::DisplayRole) {
183 const ProfileTableRow& row = m_rowData[index.row()];
184
185 switch(index.column()) {
186 case COLUMN_PROGRAM:
187 return row.program;
188 case COLUMN_USAGES:
189 return row.uses;
190 case COLUMN_GPU_TIME:
191 return row.gpuTime;
192 case COLUMN_CPU_TIME:
193 return row.cpuTime;
194 case COLUMN_PIXELS_DRAWN:
195 return row.pixels;
196 case COLUMN_GPU_AVERAGE:
197 return (row.uses <= 0) ? 0 : (row.gpuTime / row.uses);
198 case COLUMN_CPU_AVERAGE:
199 return (row.uses <= 0) ? 0 : (row.cpuTime / row.uses);
200 case COLUMN_PIXELS_AVERAGE:
201 return (row.uses <= 0) ? 0 : (row.pixels / row.uses);
202 }
203 } else if (role == Qt::TextAlignmentRole) {
204 return Qt::AlignRight;
205 }
206
207 return QVariant();
208}
209
210
211QVariant ProfileTableModel::headerData(int section, Qt::Orientation orientation, int role) const
212{
213 if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
214 if (section >= 0 && section < MAX_COLUMN) {
215 return columnNames[section];
216 }
217 }
218
219 return QVariant();
220}
221
222
223class ProgramSorter {
224public:
225 ProgramSorter(int column, Qt::SortOrder order)
226 : mSortColumn(column),
227 mSortOrder(order)
228 {
229 }
230
231 bool operator()(const ProfileTableRow &p1, const ProfileTableRow &p2) const
232 {
233 bool result = true;
234
235 switch(mSortColumn) {
236 case COLUMN_PROGRAM:
237 result = p1.program < p2.program;
238 break;
239 case COLUMN_USAGES:
240 result = p1.uses < p2.uses;
241 break;
242 case COLUMN_GPU_TIME:
243 result = p1.gpuTime < p2.gpuTime;
244 break;
245 case COLUMN_CPU_TIME:
246 result = p1.cpuTime < p2.cpuTime;
247 break;
248 case COLUMN_PIXELS_DRAWN:
249 result = p1.pixels < p2.pixels;
250 break;
251 case COLUMN_GPU_AVERAGE:
James Benton08717052012-08-08 17:43:52 +0100252 result = ((p1.uses <= 0) ? 0 : (p1.gpuTime / p1.uses)) < ((p2.uses <= 0) ? 0 : (p2.gpuTime / p2.uses));
James Bentonfc4f55a2012-08-08 17:09:07 +0100253 break;
254 case COLUMN_CPU_AVERAGE:
James Benton08717052012-08-08 17:43:52 +0100255 result = ((p1.uses <= 0) ? 0 : (p1.cpuTime / p1.uses)) < ((p2.uses <= 0) ? 0 : (p2.cpuTime / p2.uses));
James Bentonfc4f55a2012-08-08 17:09:07 +0100256 break;
257 case COLUMN_PIXELS_AVERAGE:
James Benton08717052012-08-08 17:43:52 +0100258 result = ((p1.uses <= 0) ? 0 : (p1.pixels / p1.uses)) < ((p2.uses <= 0) ? 0 : (p2.pixels / p2.uses));
James Bentonfc4f55a2012-08-08 17:09:07 +0100259 break;
260 }
261
262 if (mSortOrder == Qt::DescendingOrder) {
263 return !result;
264 } else {
265 return result;
266 }
267 }
268
269private:
270 int mSortColumn;
271 Qt::SortOrder mSortOrder;
272};
273
274
275void ProfileTableModel::sort(int column, Qt::SortOrder order) {
276 m_sortColumn = column;
277 m_sortOrder = order;
278 qSort(m_rowData.begin(), m_rowData.end(), ProgramSorter(column, order));
279 emit dataChanged(createIndex(0, 0), createIndex(m_rowData.size(), MAX_COLUMN));
280}
281
282
283#include "profiletablemodel.moc"