206 lines
3.0 KiB
C++
206 lines
3.0 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();
|
|
}
|
|
}
|