mirror of https://github.com/PCSX2/pcsx2.git
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:
parent
79587215bb
commit
d7c1faf563
|
@ -100,6 +100,8 @@ PFNGLQUERYCOUNTERPROC glQueryCounter = NUL
|
|||
PFNGLGETQUERYOBJECTI64VPROC glGetQueryObjecti64v = NULL;
|
||||
PFNGLGETQUERYOBJECTUI64VPROC glGetQueryObjectui64v = NULL;
|
||||
PFNGLGETINTEGER64VPROC glGetInteger64v = NULL;
|
||||
PFNGLCREATEQUERIESPROC glCreateQueries = NULL;
|
||||
PFNGLDELETEQUERIESPROC glDeleteQueries = NULL;
|
||||
// GL4.0
|
||||
// GL4.1
|
||||
PFNGLBINDPROGRAMPIPELINEPROC glBindProgramPipeline = NULL;
|
||||
|
|
|
@ -268,6 +268,8 @@ extern PFNGLQUERYCOUNTERPROC glQueryCounter;
|
|||
extern PFNGLGETQUERYOBJECTI64VPROC glGetQueryObjecti64v;
|
||||
extern PFNGLGETQUERYOBJECTUI64VPROC glGetQueryObjectui64v;
|
||||
extern PFNGLGETINTEGER64VPROC glGetInteger64v;
|
||||
extern PFNGLCREATEQUERIESPROC glCreateQueries;
|
||||
extern PFNGLDELETEQUERIESPROC glDeleteQueries;
|
||||
// GL4.0
|
||||
// GL4.1
|
||||
extern PFNGLBINDPROGRAMPIPELINEPROC glBindProgramPipeline;
|
||||
|
|
|
@ -1689,7 +1689,9 @@ EXPORT_C GSReplay(char* lpszCmdLine, int renderer)
|
|||
// Ensure the rendering is complete to measure correctly the time.
|
||||
glFinish();
|
||||
|
||||
if (finished > 90) {
|
||||
if (finished >= 200) {
|
||||
; // Nop for Nvidia Profiler
|
||||
} else if (finished > 90) {
|
||||
sleep(1);
|
||||
} else {
|
||||
unsigned long end = timeGetTime();
|
||||
|
@ -1724,7 +1726,7 @@ EXPORT_C GSReplay(char* lpszCmdLine, int renderer)
|
|||
fprintf(stderr, "\n\nMean: %fms\n", mean);
|
||||
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, "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
|
||||
total_frame_nb *= 1024;
|
||||
|
@ -1748,4 +1750,3 @@ EXPORT_C GSReplay(char* lpszCmdLine, int renderer)
|
|||
GSshutdown();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -71,6 +71,7 @@ GSDeviceOGL::GSDeviceOGL()
|
|||
memset(&m_date, 0, sizeof(m_date));
|
||||
memset(&m_shadeboost, 0, sizeof(m_shadeboost));
|
||||
memset(&m_om_dss, 0, sizeof(m_om_dss));
|
||||
memset(&m_profiler, 0 , sizeof(m_profiler));
|
||||
GLState::Clear();
|
||||
|
||||
// Reset the debug file
|
||||
|
@ -94,6 +95,10 @@ GSDeviceOGL::~GSDeviceOGL()
|
|||
|
||||
GL_PUSH("GSDeviceOGL destructor");
|
||||
|
||||
if (GLLoader::in_replayer) {
|
||||
GenerateProfilerData();
|
||||
}
|
||||
|
||||
// Clean vertex buffer state
|
||||
delete m_va;
|
||||
|
||||
|
@ -139,6 +144,51 @@ GSDeviceOGL::~GSDeviceOGL()
|
|||
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)
|
||||
{
|
||||
GL_PUSH("Create surface");
|
||||
|
@ -248,6 +298,11 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
|
|||
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read);
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
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
|
||||
|
||||
m_wnd->Flip();
|
||||
|
||||
if (GLLoader::in_replayer) {
|
||||
glQueryCounter(m_profiler.timer(), GL_TIMESTAMP);
|
||||
m_profiler.last_query++;
|
||||
}
|
||||
}
|
||||
|
||||
void GSDeviceOGL::BeforeDraw()
|
||||
|
|
|
@ -449,6 +449,13 @@ public:
|
|||
GLuint ps;
|
||||
} 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_gs[1<<2];
|
||||
GLuint m_ps_ss[1<<4];
|
||||
|
@ -484,6 +491,8 @@ public:
|
|||
GSDeviceOGL();
|
||||
virtual ~GSDeviceOGL();
|
||||
|
||||
void GenerateProfilerData();
|
||||
|
||||
static void CheckDebugLog();
|
||||
// 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);
|
||||
|
@ -555,7 +564,6 @@ public:
|
|||
void SelfShaderTestRun(const string& dir, const string& file, const PSSelector& sel, int& nb_shader);
|
||||
void SelfShaderTest();
|
||||
|
||||
|
||||
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 SetupCB(const VSConstantBuffer* vs_cb, const PSConstantBuffer* ps_cb);
|
||||
|
|
|
@ -84,15 +84,17 @@ void GSWndGL::PopulateGlFunction()
|
|||
GL_EXT_LOAD(glClientWaitSync);
|
||||
GL_EXT_LOAD(glFlushMappedBufferRange);
|
||||
// Query object
|
||||
GL_EXT_LOAD(glBeginQuery);
|
||||
GL_EXT_LOAD(glEndQuery);
|
||||
GL_EXT_LOAD(glGetQueryiv);
|
||||
GL_EXT_LOAD(glGetQueryObjectiv);
|
||||
GL_EXT_LOAD(glGetQueryObjectuiv);
|
||||
GL_EXT_LOAD(glQueryCounter);
|
||||
GL_EXT_LOAD(glGetQueryObjecti64v);
|
||||
GL_EXT_LOAD(glGetQueryObjectui64v);
|
||||
GL_EXT_LOAD(glGetInteger64v);
|
||||
GL_EXT_LOAD_OPT(glBeginQuery);
|
||||
GL_EXT_LOAD_OPT(glEndQuery);
|
||||
GL_EXT_LOAD_OPT(glGetQueryiv);
|
||||
GL_EXT_LOAD_OPT(glGetQueryObjectiv);
|
||||
GL_EXT_LOAD_OPT(glGetQueryObjectuiv);
|
||||
GL_EXT_LOAD_OPT(glQueryCounter);
|
||||
GL_EXT_LOAD_OPT(glGetQueryObjecti64v);
|
||||
GL_EXT_LOAD_OPT(glGetQueryObjectui64v);
|
||||
GL_EXT_LOAD_OPT(glGetInteger64v);
|
||||
GL_EXT_LOAD_OPT(glCreateQueries);
|
||||
GL_EXT_LOAD_OPT(glDeleteQueries);
|
||||
// GL4.0
|
||||
GL_EXT_LOAD_OPT(glBlendEquationSeparateiARB);
|
||||
GL_EXT_LOAD_OPT(glBlendFuncSeparateiARB);
|
||||
|
|
Loading…
Reference in New Issue