if (in[0] == '#' || strlen(in) < 4)
return;
- if (profile->programs.size() == 0 && profile->cpuCalls.size() == 0 && profile->frames.size() == 0) {
+ if (profile->programs.size() == 0 && profile->calls.size() == 0 && profile->frames.size() == 0) {
lastGpuTime = 0;
lastCpuTime = 0;
}
line >> type;
if (type.compare("call") == 0) {
- Profile::DrawCall draw;
- unsigned program;
-
- line >> draw.no
- >> draw.gpuStart
- >> draw.gpuDuration
- >> draw.cpuStart
- >> draw.cpuDuration
- >> draw.pixels
- >> program
- >> draw.name;
-
- if (lastGpuTime < draw.gpuStart + draw.gpuDuration) {
- lastGpuTime = draw.gpuStart + draw.gpuDuration;
+ Profile::Call call;
+ unsigned programNo;
+
+ line >> call.no
+ >> call.gpuStart
+ >> call.gpuDuration
+ >> call.cpuStart
+ >> call.cpuDuration
+ >> call.pixels
+ >> programNo
+ >> call.name;
+
+ if (lastGpuTime < call.gpuStart + call.gpuDuration) {
+ lastGpuTime = call.gpuStart + call.gpuDuration;
}
- if (lastCpuTime < draw.cpuStart + draw.cpuDuration) {
- lastCpuTime = draw.cpuStart + draw.cpuDuration;
+ if (lastCpuTime < call.cpuStart + call.cpuDuration) {
+ lastCpuTime = call.cpuStart + call.cpuDuration;
}
- if (draw.pixels >= 0) {
- if (profile->programs.size() <= program) {
- profile->programs.resize(program + 1);
+ profile->calls.push_back(call);
+
+ if (call.pixels >= 0) {
+ if (profile->programs.size() <= programNo) {
+ profile->programs.resize(programNo + 1);
}
- profile->programs[program].cpuTotal += draw.cpuDuration;
- profile->programs[program].gpuTotal += draw.gpuDuration;
- profile->programs[program].pixelTotal += draw.pixels;
- profile->programs[program].drawCalls.push_back(draw);
+ Profile::Program& program = profile->programs[programNo];
+ program.cpuTotal += call.cpuDuration;
+ program.gpuTotal += call.gpuDuration;
+ program.pixelTotal += call.pixels;
+ program.calls.push_back(profile->calls.size() - 1);
}
-
- Profile::CpuCall call;
- call.no = draw.no;
- call.name = draw.name;
- call.cpuStart = draw.cpuStart;
- call.cpuDuration = draw.cpuDuration;
- profile->cpuCalls.push_back(call);
} else if (type.compare("frame_end") == 0) {
Profile::Frame frame;
frame.no = profile->frames.size();
if (frame.no == 0) {
frame.gpuStart = 0;
frame.cpuStart = 0;
+ frame.calls.begin = 0;
} else {
frame.gpuStart = profile->frames.back().gpuStart + profile->frames.back().gpuDuration;
frame.cpuStart = profile->frames.back().cpuStart + profile->frames.back().cpuDuration;
+ frame.calls.begin = profile->frames.back().calls.end + 1;
}
frame.gpuDuration = lastGpuTime - frame.gpuStart;
frame.cpuDuration = lastCpuTime - frame.cpuStart;
+ frame.calls.end = profile->calls.size() - 1;
+
profile->frames.push_back(frame);
}
}
{
struct Profile {
- struct CpuCall {
- unsigned no;
-
- int64_t cpuStart;
- int64_t cpuDuration;
-
- std::string name;
- };
-
- struct DrawCall {
+ struct Call {
unsigned no;
int64_t gpuStart;
int64_t cpuStart;
int64_t cpuDuration;
+
+ /* Indices to profile->calls array */
+ struct {
+ unsigned begin;
+ unsigned end;
+ } calls;
};
struct Program {
uint64_t gpuTotal;
uint64_t cpuTotal;
uint64_t pixelTotal;
- std::vector<DrawCall> drawCalls;
+
+ /* Indices to profile->calls array */
+ std::vector<unsigned> calls;
};
+ std::vector<Call> calls;
std::vector<Frame> frames;
std::vector<Program> programs;
- std::vector<CpuCall> cpuCalls;
};
class Profiler
void ProfileDialog::tableDoubleClicked(const QModelIndex& index)
{
ProfileTableModel* model = (ProfileTableModel*)m_table->model();
- const trace::Profile::DrawCall* call = model->getJumpCall(index);
+ const trace::Profile::Call* call = model->getJumpCall(index);
if (call) {
emit jumpToCall(call->no);
#include "profiletablemodel.h"
+typedef trace::Profile::Call Call;
typedef trace::Profile::Frame Frame;
typedef trace::Profile::Program Program;
-typedef trace::Profile::CpuCall CpuCall;
-typedef trace::Profile::DrawCall DrawCall;
enum {
COLUMN_PROGRAM,
}
for (std::vector<Program>::const_iterator itr = m_profile->programs.begin(); itr != m_profile->programs.end(); ++itr) {
- ProfileTableRow* row = getRow(itr - m_profile->programs.begin());
+ ProfileTableRow* row = NULL;
const Program& program = *itr;
- for (std::vector<DrawCall>::const_iterator jtr = program.drawCalls.begin(); jtr != program.drawCalls.end(); ++jtr) {
- const DrawCall& call = *jtr;
+ for (std::vector<unsigned>::const_iterator jtr = program.calls.begin(); jtr != program.calls.end(); ++jtr) {
+ const Call& call = m_profile->calls[*jtr];
if (call.cpuStart > m_timeMax) {
break;
continue;
}
+ if (!row) {
+ row = getRow(itr - m_profile->programs.begin());
+ }
+
row->uses++;
row->pixels += call.pixels;
row->gpuTime += call.gpuDuration;
/**
* Get the appropriate call associated with an item in the table
*/
-const DrawCall* ProfileTableModel::getJumpCall(const QModelIndex & index) const {
+const trace::Profile::Call *ProfileTableModel::getJumpCall(const QModelIndex & index) const {
const ProfileTableRow& row = m_rowData[index.row()];
switch(index.column()) {
qulonglong cpuTime;
qulonglong pixels;
- const trace::Profile::DrawCall* longestGpu;
- const trace::Profile::DrawCall* longestCpu;
- const trace::Profile::DrawCall* longestPixel;
+ const trace::Profile::Call* longestGpu;
+ const trace::Profile::Call* longestCpu;
+ const trace::Profile::Call* longestPixel;
};
class ProfileTableModel : public QAbstractTableModel
void setProfile(trace::Profile* profile);
void setTimeSelection(int64_t start, int64_t end);
- const trace::Profile::DrawCall* getJumpCall(const QModelIndex & index) const;
+ const trace::Profile::Call* getJumpCall(const QModelIndex & index) const;
virtual int rowCount(const QModelIndex & parent) const;
virtual int columnCount(const QModelIndex & parent) const;
#include <QWheelEvent>
#include <QApplication>
+typedef trace::Profile::Call Call;
typedef trace::Profile::Frame Frame;
typedef trace::Profile::Program Program;
-typedef trace::Profile::CpuCall CpuCall;
-typedef trace::Profile::DrawCall DrawCall;
TimelineWidget::TimelineWidget(QWidget *parent)
: QWidget(parent),
itr = begin + pos;
}
- if (lower <= upper)
+ if (lower <= upper) {
return itr;
- else
+ } else {
+ return end;
+ }
+}
+
+
+/**
+ * Binary Search for a time in start+durations on an array of indices
+ */
+std::vector<unsigned>::const_iterator binarySearchTimespanIndexed(
+ const std::vector<Call>& calls,
+ std::vector<unsigned>::const_iterator begin,
+ std::vector<unsigned>::const_iterator end,
+ int64_t time)
+{
+ int lower = 0;
+ int upper = end - begin;
+ int pos = (lower + upper) / 2;
+ std::vector<unsigned>::const_iterator itr = begin + pos;
+
+ while (lower <= upper) {
+ const Call& call = calls[*itr];
+
+ if (call.gpuStart <= time && call.gpuStart + call.gpuDuration > time) {
+ break;
+ }
+
+ if (call.gpuStart > time) {
+ upper = pos - 1;
+ } else {
+ lower = pos + 1;
+ }
+
+ pos = (lower + upper) / 2;
+ itr = begin + pos;
+ }
+
+ if (lower <= upper) {
+ return itr;
+ } else {
return end;
+ }
}
/**
* Find the frame at time
*/
-const Frame* TimelineWidget::frameAtTime(int64_t time) {
+const Frame* TimelineWidget::frameAtTime(int64_t time)
+{
if (!m_profile) {
return NULL;
}
time);
if (res != m_profile->frames.end()) {
- const Frame& frame = *res;
- return &frame;
+ return &*res;
}
return NULL;
/**
* Find the CPU call at time
*/
-const CpuCall* TimelineWidget::cpuCallAtTime(int64_t time) {
+const Call* TimelineWidget::cpuCallAtTime(int64_t time)
+{
if (!m_profile) {
return NULL;
}
- std::vector<CpuCall>::const_iterator res
- = binarySearchTimespan<CpuCall, &CpuCall::cpuStart, &CpuCall::cpuDuration>(
- m_profile->cpuCalls.begin(),
- m_profile->cpuCalls.end(),
+ std::vector<Call>::const_iterator res
+ = binarySearchTimespan<Call, &Call::cpuStart, &Call::cpuDuration>(
+ m_profile->calls.begin(),
+ m_profile->calls.end(),
time);
- if (res != m_profile->cpuCalls.end()) {
- const CpuCall& call = *res;
- return &call;
+ if (res != m_profile->calls.end()) {
+ return &*res;
}
return NULL;
/**
* Find the draw call at time
*/
-const DrawCall* TimelineWidget::drawCallAtTime(int program, int64_t time) {
+const Call* TimelineWidget::drawCallAtTime(int64_t time, int program)
+{
if (!m_profile) {
return NULL;
}
- std::vector<DrawCall>& drawCalls = m_profile->programs[program].drawCalls;
-
- std::vector<DrawCall>::const_iterator res
- = binarySearchTimespan<DrawCall, &DrawCall::gpuStart, &DrawCall::gpuDuration>(
- drawCalls.begin(),
- drawCalls.end(),
+ std::vector<unsigned>::const_iterator res
+ = binarySearchTimespanIndexed(
+ m_profile->calls,
+ m_profile->programs[program].calls.begin(),
+ m_profile->programs[program].calls.end(),
time);
- if (res != drawCalls.end()) {
- const DrawCall& call = *res;
- return &call;
+ if (res != m_profile->programs[program].calls.end()) {
+ return &m_profile->calls[*res];
}
return NULL;
int y = m_mousePosition.y() - m_axisHeight;
if (y < m_rowHeight) {
- const CpuCall* call = cpuCallAtTime(time);
+ const Call* call = cpuCallAtTime(time);
if (call) {
QString text;
int row = (y - m_rowHeight + m_scrollY) / m_rowHeight;
if (row < m_rowPrograms.size()) {
- int program = m_rowPrograms[row];
- const DrawCall* call = drawCallAtTime(program, time);
+ const Call* call = drawCallAtTime(time, m_rowPrograms[row]);
if (call) {
QString text;
}
} else if (row == 0) {
/* CPU Calls */
- const CpuCall* call = cpuCallAtTime(time);
+ const Call* call = cpuCallAtTime(time);
if (call) {
emit jumpToCall(call->no);
}
} else if (row > 0) {
/* Draw Calls */
- int program = m_rowPrograms[row - 1 + m_row];
- const DrawCall* call = drawCallAtTime(program, time);
+ const Call* call = drawCallAtTime(time, 0);
if (call) {
emit jumpToCall(call->no);
lastX = 0;
heat = 0;
- for (std::vector<DrawCall>::const_iterator itr = program.drawCalls.begin(); itr != program.drawCalls.end(); ++itr) {
- const DrawCall& call = *itr;
+ for (std::vector<unsigned>::const_iterator itr = program.calls.begin(); itr != program.calls.end(); ++itr) {
+ const Call& call = m_profile->calls[*itr];
int64_t gpuEnd = call.gpuStart + call.gpuDuration;
if (call.gpuStart > timeEnd) {
painter.translate(m_axisWidth, m_axisHeight);
painter.fillRect(0, 0, m_viewWidth, m_rowHeight, Qt::white);
- for (std::vector<CpuCall>::const_iterator itr = m_profile->cpuCalls.begin(); itr != m_profile->cpuCalls.end(); ++itr) {
- const CpuCall& call = *itr;
+ for (std::vector<Call>::const_iterator itr = m_profile->calls.begin(); itr != m_profile->calls.end(); ++itr) {
+ const Call& call = *itr;
int64_t cpuEnd = call.cpuStart + call.cpuDuration;
if (call.cpuStart > timeEnd) {
void calculateRows();
const trace::Profile::Frame* frameAtTime(int64_t time);
- const trace::Profile::CpuCall* cpuCallAtTime(int64_t time);
- const trace::Profile::DrawCall* drawCallAtTime(int program, int64_t time);
+ const trace::Profile::Call* cpuCallAtTime(int64_t time);
+ const trace::Profile::Call* drawCallAtTime(int64_t time, int program);
private:
/* Data */