Factor out performance timers into separate files
This should make graphics.cpp somewhat easier to navigate/read. GL_EXT_timer_query is also made optional, and if it's not present dummy functions will be called instead.
This commit is contained in:
		
							parent
							
								
									4ff563725b
								
							
						
					
					
						commit
						307eeb732d
					
				
					 4 changed files with 237 additions and 200 deletions
				
			
		
							
								
								
									
										6
									
								
								mkxp.pro
									
										
									
									
									
								
							
							
						
						
									
										6
									
								
								mkxp.pro
									
										
									
									
									
								
							| 
						 | 
					@ -60,7 +60,8 @@ HEADERS += \
 | 
				
			||||||
	src/gl-util.h \
 | 
						src/gl-util.h \
 | 
				
			||||||
	src/util.h \
 | 
						src/util.h \
 | 
				
			||||||
	src/config.h \
 | 
						src/config.h \
 | 
				
			||||||
	src/tileatlas.h
 | 
						src/tileatlas.h \
 | 
				
			||||||
 | 
						src/perftimer.h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SOURCES += \
 | 
					SOURCES += \
 | 
				
			||||||
	src/main.cpp \
 | 
						src/main.cpp \
 | 
				
			||||||
| 
						 | 
					@ -87,7 +88,8 @@ SOURCES += \
 | 
				
			||||||
	src/debuglogger.cpp \
 | 
						src/debuglogger.cpp \
 | 
				
			||||||
	src/etc.cpp \
 | 
						src/etc.cpp \
 | 
				
			||||||
	src/config.cpp \
 | 
						src/config.cpp \
 | 
				
			||||||
	src/tileatlas.cpp
 | 
						src/tileatlas.cpp \
 | 
				
			||||||
 | 
						src/perftimer.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EMBED = shader/transSimple.frag \
 | 
					EMBED = shader/transSimple.frag \
 | 
				
			||||||
        shader/trans.frag \
 | 
					        shader/trans.frag \
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										211
									
								
								src/graphics.cpp
									
										
									
									
									
								
							
							
						
						
									
										211
									
								
								src/graphics.cpp
									
										
									
									
									
								
							| 
						 | 
					@ -33,187 +33,11 @@
 | 
				
			||||||
#include "bitmap.h"
 | 
					#include "bitmap.h"
 | 
				
			||||||
#include "etc-internal.h"
 | 
					#include "etc-internal.h"
 | 
				
			||||||
#include "binding.h"
 | 
					#include "binding.h"
 | 
				
			||||||
 | 
					#include "perftimer.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "SDL2/SDL_video.h"
 | 
					#include "SDL2/SDL_video.h"
 | 
				
			||||||
#include "SDL2/SDL_timer.h"
 | 
					#include "SDL2/SDL_timer.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "stdint.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "SFML/System/Clock.hpp"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
//			qDebug() << "TimerQuery result not ready";
 | 
					 | 
				
			||||||
			return false;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		glGetQueryObjectui64v(query, GL_QUERY_RESULT, result);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (glGetError() == GL_INVALID_OPERATION)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			qDebug() << "Something went wrong with getting TimerQuery results";
 | 
					 | 
				
			||||||
			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;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct GPUTimer
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	TimerQuery queries[2];
 | 
					 | 
				
			||||||
	const int iter;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	uchar ind;
 | 
					 | 
				
			||||||
	uint64_t acc;
 | 
					 | 
				
			||||||
	int32_t counter;
 | 
					 | 
				
			||||||
	bool first;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	GPUTimer(int iter)
 | 
					 | 
				
			||||||
	    : iter(iter),
 | 
					 | 
				
			||||||
	      ind(0),
 | 
					 | 
				
			||||||
	      acc(0),
 | 
					 | 
				
			||||||
	      counter(0),
 | 
					 | 
				
			||||||
	      first(true)
 | 
					 | 
				
			||||||
	{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	void startTiming()
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		queries[ind].begin();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	void endTiming()
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		queries[ind].end();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (first)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			first = false;
 | 
					 | 
				
			||||||
			return;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		swapInd();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		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()
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		ind = ind ? 0 : 1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct CPUTimer
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	const int iter;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	uint64_t acc;
 | 
					 | 
				
			||||||
	int32_t counter;
 | 
					 | 
				
			||||||
	sf::Clock clock;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	CPUTimer(int iter)
 | 
					 | 
				
			||||||
	    : iter(iter),
 | 
					 | 
				
			||||||
	      acc(0),
 | 
					 | 
				
			||||||
	      counter(0)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	void startTiming()
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		clock.restart();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	void endTiming()
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		acc += clock.getElapsedTime().asMicroseconds();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (++counter < iter)
 | 
					 | 
				
			||||||
			return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		qDebug() << "Avg. CPU time:" << ((double) acc / (iter * 1000)) << "ms";
 | 
					 | 
				
			||||||
		acc = counter = 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct PingPong
 | 
					struct PingPong
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	TEXFBO rt[2];
 | 
						TEXFBO rt[2];
 | 
				
			||||||
| 
						 | 
					@ -436,19 +260,6 @@ struct FPSLimiter
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Timer
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	uint64_t lastTicks;
 | 
					 | 
				
			||||||
	uint64_t acc;
 | 
					 | 
				
			||||||
	int counter;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Timer()
 | 
					 | 
				
			||||||
	    : lastTicks(SDL_GetPerformanceCounter()),
 | 
					 | 
				
			||||||
	      acc(0),
 | 
					 | 
				
			||||||
	      counter(0)
 | 
					 | 
				
			||||||
	{}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct GraphicsPrivate
 | 
					struct GraphicsPrivate
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/* Screen resolution, ie. the resolution at which
 | 
						/* Screen resolution, ie. the resolution at which
 | 
				
			||||||
| 
						 | 
					@ -477,8 +288,8 @@ struct GraphicsPrivate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	FPSLimiter fpsLimiter;
 | 
						FPSLimiter fpsLimiter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	GPUTimer gpuTimer;
 | 
						PerfTimer *gpuTimer;
 | 
				
			||||||
	CPUTimer cpuTimer;
 | 
						PerfTimer *cpuTimer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool frozen;
 | 
						bool frozen;
 | 
				
			||||||
	TEXFBO frozenScene;
 | 
						TEXFBO frozenScene;
 | 
				
			||||||
| 
						 | 
					@ -495,10 +306,11 @@ struct GraphicsPrivate
 | 
				
			||||||
	      frameCount(0),
 | 
						      frameCount(0),
 | 
				
			||||||
	      brightness(255),
 | 
						      brightness(255),
 | 
				
			||||||
	      fpsLimiter(frameRate),
 | 
						      fpsLimiter(frameRate),
 | 
				
			||||||
	      gpuTimer(frameRate),
 | 
					 | 
				
			||||||
	      cpuTimer(frameRate),
 | 
					 | 
				
			||||||
	      frozen(false)
 | 
						      frozen(false)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
							gpuTimer = createGPUTimer(frameRate);
 | 
				
			||||||
 | 
							cpuTimer = createCPUTimer(frameRate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		TEXFBO::init(frozenScene);
 | 
							TEXFBO::init(frozenScene);
 | 
				
			||||||
		TEXFBO::allocEmpty(frozenScene, scRes.x, scRes.y);
 | 
							TEXFBO::allocEmpty(frozenScene, scRes.x, scRes.y);
 | 
				
			||||||
		TEXFBO::linkFBO(frozenScene);
 | 
							TEXFBO::linkFBO(frozenScene);
 | 
				
			||||||
| 
						 | 
					@ -517,6 +329,9 @@ struct GraphicsPrivate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	~GraphicsPrivate()
 | 
						~GraphicsPrivate()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
							delete gpuTimer;
 | 
				
			||||||
 | 
							delete cpuTimer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		TEXFBO::fini(frozenScene);
 | 
							TEXFBO::fini(frozenScene);
 | 
				
			||||||
		TEXFBO::fini(currentScene);
 | 
							TEXFBO::fini(currentScene);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -627,8 +442,8 @@ void Graphics::update()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	gState->checkShutdown();
 | 
						gState->checkShutdown();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//	p->cpuTimer.endTiming();
 | 
					//	p->cpuTimer->endTiming();
 | 
				
			||||||
//	p->gpuTimer.startTiming();
 | 
					//	p->gpuTimer->startTiming();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (p->frozen)
 | 
						if (p->frozen)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
| 
						 | 
					@ -636,8 +451,8 @@ void Graphics::update()
 | 
				
			||||||
	p->checkResize();
 | 
						p->checkResize();
 | 
				
			||||||
	p->redrawScreen();
 | 
						p->redrawScreen();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//	p->gpuTimer.endTiming();
 | 
					//	p->gpuTimer->endTiming();
 | 
				
			||||||
//	p->cpuTimer.startTiming();
 | 
					//	p->cpuTimer->startTiming();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Graphics::wait(int duration)
 | 
					void Graphics::wait(int duration)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										202
									
								
								src/perftimer.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								src/perftimer.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,202 @@
 | 
				
			||||||
 | 
					#include "perftimer.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "SDL2/SDL_timer.h"
 | 
				
			||||||
 | 
					#include "GL/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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct GPUTimerGLQuery : public PerfTimer
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						TimerQuery queries[2];
 | 
				
			||||||
 | 
						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();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (first)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								first = false;
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							swapInd();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							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()
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							ind = ind ? 0 : 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										18
									
								
								src/perftimer.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/perftimer.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,18 @@
 | 
				
			||||||
 | 
					#ifndef PERFTIMER_H
 | 
				
			||||||
 | 
					#define PERFTIMER_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct PerfTimer
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						virtual ~PerfTimer() {}
 | 
				
			||||||
 | 
						virtual void startTiming() = 0;
 | 
				
			||||||
 | 
						virtual void endTiming() = 0;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Create timers that run on either CPU or GPU.
 | 
				
			||||||
 | 
					 * After 'iter' pairs of startTiming()/endTiming(),
 | 
				
			||||||
 | 
					 * they will calculate the average measurement and
 | 
				
			||||||
 | 
					 * print it to the console */
 | 
				
			||||||
 | 
					PerfTimer *createGPUTimer(int iter);
 | 
				
			||||||
 | 
					PerfTimer *createCPUTimer(int iter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // PERFTIMER_H
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue