mkxp/src/perftimer.cpp
Jonas Kulla ef2430e0c3 Sanitize #include statements
The general rule I'm aiming for is to <> include
system wide / installed paths / generally everything
that's outside the git managed source tree (this means
mruby paths too!), and "" include everything else,
ie. local mkxp headers.

The only current exception are the mri headers, which
all have './' at their front as to not clash with
system wide ruby headers. I'm leaving them be for now
until I can come up with a better general solution.
2013-12-04 17:48:37 +01:00

205 lines
3 KiB
C++

#include "perftimer.h"
#include <SDL_timer.h>
#include <glew.h>
#include <QDebug>
struct TimerQuery
{
GLuint query;
static bool queryActive;
bool thisQueryActive;
TimerQuery()
: thisQueryActive(false)
{
glGenQueries(1, &query);
}
void begin()
{
if (queryActive)
return;
if (thisQueryActive)
return;
glBeginQuery(GL_TIME_ELAPSED, query);
queryActive = true;
thisQueryActive = true;
}
void end()
{
if (!thisQueryActive)
return;
glEndQuery(GL_TIME_ELAPSED);
queryActive = false;
thisQueryActive = false;
}
bool getResult(GLuint64 *result)
{
if (thisQueryActive)
return false;
GLint isReady = GL_FALSE;
glGetQueryObjectiv(query, GL_QUERY_RESULT_AVAILABLE, &isReady);
if (isReady != GL_TRUE)
return false;
glGetQueryObjectui64v(query, GL_QUERY_RESULT, result);
if (glGetError() == GL_INVALID_OPERATION)
return false;
return true;
}
GLuint64 getResultSync()
{
if (thisQueryActive)
return 0;
GLuint64 result;
GLint isReady = GL_FALSE;
while (isReady == GL_FALSE)
glGetQueryObjectiv(query, GL_QUERY_RESULT_AVAILABLE, &isReady);
glGetQueryObjectui64v(query, GL_QUERY_RESULT, &result);
return result;
}
~TimerQuery()
{
if (thisQueryActive)
end();
glDeleteQueries(1, &query);
}
};
bool TimerQuery::queryActive = false;
#define GPU_QUERIES 2
struct GPUTimerGLQuery : public PerfTimer
{
TimerQuery queries[GPU_QUERIES];
const int iter;
uint8_t ind;
uint64_t acc;
int32_t counter;
bool first;
GPUTimerGLQuery(int iter)
: iter(iter),
ind(0),
acc(0),
counter(0),
first(true)
{}
void startTiming()
{
queries[ind].begin();
}
void endTiming()
{
queries[ind].end();
swapInd();
if (first)
{
first = false;
return;
}
GLuint64 result;
if (!queries[ind].getResult(&result))
return;
acc += result;
if (++counter < iter)
return;
qDebug() << " "
"Avg. GPU time:" << ((double) acc / (iter * 1000 * 1000)) << "ms";
acc = counter = 0;
}
void swapInd()
{
if (++ind > GPU_QUERIES)
ind = 0;
}
};
struct GPUTimerDummy : public PerfTimer
{
void startTiming() {}
void endTiming() {}
};
struct CPUTimer : public PerfTimer
{
const int iter;
uint64_t acc;
int32_t counter;
Uint64 ticks;
Uint64 perfFreq;
CPUTimer(int iter)
: iter(iter),
acc(0),
counter(0),
ticks(0)
{
perfFreq = SDL_GetPerformanceFrequency();
}
void startTiming()
{
ticks = SDL_GetPerformanceCounter();
}
void endTiming()
{
acc += SDL_GetPerformanceCounter() - ticks;
if (++counter < iter)
return;
qDebug() << "Avg. CPU time:" << ((double) acc / (iter * (perfFreq / 1000))) << "ms";
acc = counter = 0;
}
};
PerfTimer *createCPUTimer(int iter)
{
return new CPUTimer(iter);
}
PerfTimer *createGPUTimer(int iter)
{
if (GLEW_EXT_timer_query)
{
return new GPUTimerGLQuery(iter);
}
else
{
qDebug() << "GL_EXT_timer_query not present: cannot measure GPU performance";
return new GPUTimerDummy();
}
}