mkxp/src/perftimer.cpp
Edward Rudd eacc143ea0 update extension usage..
nearly all of the previous required extensions are CORE in OpenGL 2.0
the remaining ones need to have fallback checks for ARB vs EXT vs APPLE 
variants..
2013-12-31 16:31:03 -05:00

205 lines
3 KiB
C++

#include "perftimer.h"
#include <SDL_timer.h>
#include <glew.h>
#include "debugwriter.h"
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;
Debug() << " "
"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;
Debug() << "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_ARB_timer_query || GLEW_EXT_timer_query)
{
return new GPUTimerGLQuery(iter);
}
else
{
Debug() << "GL_EXT_timer_query not present: cannot measure GPU performance";
return new GPUTimerDummy();
}
}