gsdx ogl: add GPU timers to measure time between 2 vsync

So far only basic stuff (min/mean/max frame rendering time)
This commit is contained in:
Gregory Hainaut 2016-06-26 15:27:57 +02:00
parent 79587215bb
commit d7c1faf563
6 changed files with 88 additions and 13 deletions

View File

@ -100,6 +100,8 @@ PFNGLQUERYCOUNTERPROC glQueryCounter = NUL
PFNGLGETQUERYOBJECTI64VPROC glGetQueryObjecti64v = NULL; PFNGLGETQUERYOBJECTI64VPROC glGetQueryObjecti64v = NULL;
PFNGLGETQUERYOBJECTUI64VPROC glGetQueryObjectui64v = NULL; PFNGLGETQUERYOBJECTUI64VPROC glGetQueryObjectui64v = NULL;
PFNGLGETINTEGER64VPROC glGetInteger64v = NULL; PFNGLGETINTEGER64VPROC glGetInteger64v = NULL;
PFNGLCREATEQUERIESPROC glCreateQueries = NULL;
PFNGLDELETEQUERIESPROC glDeleteQueries = NULL;
// GL4.0 // GL4.0
// GL4.1 // GL4.1
PFNGLBINDPROGRAMPIPELINEPROC glBindProgramPipeline = NULL; PFNGLBINDPROGRAMPIPELINEPROC glBindProgramPipeline = NULL;

View File

@ -268,6 +268,8 @@ extern PFNGLQUERYCOUNTERPROC glQueryCounter;
extern PFNGLGETQUERYOBJECTI64VPROC glGetQueryObjecti64v; extern PFNGLGETQUERYOBJECTI64VPROC glGetQueryObjecti64v;
extern PFNGLGETQUERYOBJECTUI64VPROC glGetQueryObjectui64v; extern PFNGLGETQUERYOBJECTUI64VPROC glGetQueryObjectui64v;
extern PFNGLGETINTEGER64VPROC glGetInteger64v; extern PFNGLGETINTEGER64VPROC glGetInteger64v;
extern PFNGLCREATEQUERIESPROC glCreateQueries;
extern PFNGLDELETEQUERIESPROC glDeleteQueries;
// GL4.0 // GL4.0
// GL4.1 // GL4.1
extern PFNGLBINDPROGRAMPIPELINEPROC glBindProgramPipeline; extern PFNGLBINDPROGRAMPIPELINEPROC glBindProgramPipeline;

View File

@ -1689,7 +1689,9 @@ EXPORT_C GSReplay(char* lpszCmdLine, int renderer)
// Ensure the rendering is complete to measure correctly the time. // Ensure the rendering is complete to measure correctly the time.
glFinish(); glFinish();
if (finished > 90) { if (finished >= 200) {
; // Nop for Nvidia Profiler
} else if (finished > 90) {
sleep(1); sleep(1);
} else { } else {
unsigned long end = timeGetTime(); unsigned long end = timeGetTime();
@ -1724,7 +1726,7 @@ EXPORT_C GSReplay(char* lpszCmdLine, int renderer)
fprintf(stderr, "\n\nMean: %fms\n", mean); fprintf(stderr, "\n\nMean: %fms\n", mean);
fprintf(stderr, "Standard deviation: %fms\n", sd); fprintf(stderr, "Standard deviation: %fms\n", sd);
fprintf(stderr, "Mean by frame: %fms (%ffps)\n", mean/(float)frame_number, 1000.0f*frame_number/mean); fprintf(stderr, "Mean by frame: %fms (%ffps)\n", mean/(float)frame_number, 1000.0f*frame_number/mean);
fprintf(stderr, "Standard deviatin by frame: %fms\n", sd/(float)frame_number); fprintf(stderr, "Standard deviation by frame: %fms\n", sd/(float)frame_number);
} }
#ifdef ENABLE_OGL_DEBUG_MEM_BW #ifdef ENABLE_OGL_DEBUG_MEM_BW
total_frame_nb *= 1024; total_frame_nb *= 1024;
@ -1748,4 +1750,3 @@ EXPORT_C GSReplay(char* lpszCmdLine, int renderer)
GSshutdown(); GSshutdown();
} }
#endif #endif

View File

@ -71,6 +71,7 @@ GSDeviceOGL::GSDeviceOGL()
memset(&m_date, 0, sizeof(m_date)); memset(&m_date, 0, sizeof(m_date));
memset(&m_shadeboost, 0, sizeof(m_shadeboost)); memset(&m_shadeboost, 0, sizeof(m_shadeboost));
memset(&m_om_dss, 0, sizeof(m_om_dss)); memset(&m_om_dss, 0, sizeof(m_om_dss));
memset(&m_profiler, 0 , sizeof(m_profiler));
GLState::Clear(); GLState::Clear();
// Reset the debug file // Reset the debug file
@ -94,6 +95,10 @@ GSDeviceOGL::~GSDeviceOGL()
GL_PUSH("GSDeviceOGL destructor"); GL_PUSH("GSDeviceOGL destructor");
if (GLLoader::in_replayer) {
GenerateProfilerData();
}
// Clean vertex buffer state // Clean vertex buffer state
delete m_va; delete m_va;
@ -139,6 +144,51 @@ GSDeviceOGL::~GSDeviceOGL()
m_shader = NULL; m_shader = NULL;
} }
void GSDeviceOGL::GenerateProfilerData()
{
if (m_profiler.last_query < 3) return;
// Point to the last query
m_profiler.last_query--;
// Wait latest quey to get valid result
GLuint available = 0;
while (!available) {
glGetQueryObjectuiv(m_profiler.timer(), GL_QUERY_RESULT_AVAILABLE, &available);
}
uint64 time_start;
uint64 time_end;
uint64 min_time = 0xFFFFFFFFFFFFFFFFull;
uint64 max_time = 0;
uint64 total = 0;
glGetQueryObjectui64v(m_profiler.timer_query[0], GL_QUERY_RESULT, &time_start);
for (uint32 q = 1; q < m_profiler.last_query; q++) {
glGetQueryObjectui64v(m_profiler.timer_query[q], GL_QUERY_RESULT, &time_end);
uint64 t = time_end - time_start;
min_time = std::min(t, min_time);
max_time = std::max(t, max_time);
total += t;
time_start = time_end;
}
glDeleteQueries(1 << 16, m_profiler.timer_query);
// FIXME remove 1/linux_replay frame info
// Add fps, deviation
// remove glFinish
double ms = 0.000001;
fprintf(stderr, "\nGenerateProfilerData:\n");
fprintf(stderr, "Min %f\n", (double)min_time * ms);
fprintf(stderr, "Mean %f\n", (double)total/(double)m_profiler.last_query * ms);
fprintf(stderr, "Max %f\n", (double)max_time * ms);
}
GSTexture* GSDeviceOGL::CreateSurface(int type, int w, int h, bool msaa, int fmt) GSTexture* GSDeviceOGL::CreateSurface(int type, int w, int h, bool msaa, int fmt)
{ {
GL_PUSH("Create surface"); GL_PUSH("Create surface");
@ -248,6 +298,11 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read); glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read);
glReadBuffer(GL_COLOR_ATTACHMENT0); glReadBuffer(GL_COLOR_ATTACHMENT0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
// Some timers to help profiling
if (GLLoader::in_replayer) {
glCreateQueries(GL_TIMESTAMP, 1 << 16, m_profiler.timer_query);
}
} }
// **************************************************************** // ****************************************************************
@ -504,6 +559,11 @@ void GSDeviceOGL::Flip()
#endif #endif
m_wnd->Flip(); m_wnd->Flip();
if (GLLoader::in_replayer) {
glQueryCounter(m_profiler.timer(), GL_TIMESTAMP);
m_profiler.last_query++;
}
} }
void GSDeviceOGL::BeforeDraw() void GSDeviceOGL::BeforeDraw()

View File

@ -449,6 +449,13 @@ public:
GLuint ps; GLuint ps;
} m_shadeboost; } m_shadeboost;
struct {
uint16 last_query;
GLuint timer_query[1<<16];
GLuint timer() { return timer_query[last_query]; }
} m_profiler;
GLuint m_vs[1]; GLuint m_vs[1];
GLuint m_gs[1<<2]; GLuint m_gs[1<<2];
GLuint m_ps_ss[1<<4]; GLuint m_ps_ss[1<<4];
@ -484,6 +491,8 @@ public:
GSDeviceOGL(); GSDeviceOGL();
virtual ~GSDeviceOGL(); virtual ~GSDeviceOGL();
void GenerateProfilerData();
static void CheckDebugLog(); static void CheckDebugLog();
// Used by OpenGL, so the same calling convention is required. // Used by OpenGL, so the same calling convention is required.
static void APIENTRY DebugOutputToFile(GLenum gl_source, GLenum gl_type, GLuint id, GLenum gl_severity, GLsizei gl_length, const GLchar *gl_message, const void* userParam); static void APIENTRY DebugOutputToFile(GLenum gl_source, GLenum gl_type, GLuint id, GLenum gl_severity, GLsizei gl_length, const GLchar *gl_message, const void* userParam);
@ -555,7 +564,6 @@ public:
void SelfShaderTestRun(const string& dir, const string& file, const PSSelector& sel, int& nb_shader); void SelfShaderTestRun(const string& dir, const string& file, const PSSelector& sel, int& nb_shader);
void SelfShaderTest(); void SelfShaderTest();
void SetupIA(const void* vertex, int vertex_count, const uint32* index, int index_count, int prim); void SetupIA(const void* vertex, int vertex_count, const uint32* index, int index_count, int prim);
void SetupPipeline(const VSSelector& vsel, const GSSelector& gsel, const PSSelector& psel); void SetupPipeline(const VSSelector& vsel, const GSSelector& gsel, const PSSelector& psel);
void SetupCB(const VSConstantBuffer* vs_cb, const PSConstantBuffer* ps_cb); void SetupCB(const VSConstantBuffer* vs_cb, const PSConstantBuffer* ps_cb);

View File

@ -84,15 +84,17 @@ void GSWndGL::PopulateGlFunction()
GL_EXT_LOAD(glClientWaitSync); GL_EXT_LOAD(glClientWaitSync);
GL_EXT_LOAD(glFlushMappedBufferRange); GL_EXT_LOAD(glFlushMappedBufferRange);
// Query object // Query object
GL_EXT_LOAD(glBeginQuery); GL_EXT_LOAD_OPT(glBeginQuery);
GL_EXT_LOAD(glEndQuery); GL_EXT_LOAD_OPT(glEndQuery);
GL_EXT_LOAD(glGetQueryiv); GL_EXT_LOAD_OPT(glGetQueryiv);
GL_EXT_LOAD(glGetQueryObjectiv); GL_EXT_LOAD_OPT(glGetQueryObjectiv);
GL_EXT_LOAD(glGetQueryObjectuiv); GL_EXT_LOAD_OPT(glGetQueryObjectuiv);
GL_EXT_LOAD(glQueryCounter); GL_EXT_LOAD_OPT(glQueryCounter);
GL_EXT_LOAD(glGetQueryObjecti64v); GL_EXT_LOAD_OPT(glGetQueryObjecti64v);
GL_EXT_LOAD(glGetQueryObjectui64v); GL_EXT_LOAD_OPT(glGetQueryObjectui64v);
GL_EXT_LOAD(glGetInteger64v); GL_EXT_LOAD_OPT(glGetInteger64v);
GL_EXT_LOAD_OPT(glCreateQueries);
GL_EXT_LOAD_OPT(glDeleteQueries);
// GL4.0 // GL4.0
GL_EXT_LOAD_OPT(glBlendEquationSeparateiARB); GL_EXT_LOAD_OPT(glBlendEquationSeparateiARB);
GL_EXT_LOAD_OPT(glBlendFuncSeparateiARB); GL_EXT_LOAD_OPT(glBlendFuncSeparateiARB);