1 #include "BenchGpuTimer_gl.h" 2 #include <string.h> 3 4 //GL 5 #define BENCH_GL_FUNCTION_TYPE 6 #if defined(SK_MESA) 7 #include <GL/osmesa.h> 8 #define SK_BENCH_CONTEXT_CHECK (NULL != OSMesaGetCurrentContext()) 9 10 #define SK_GL_GET_PROC(F) gBenchGL.f ## F = (BenchGL ## F ## Proc) \ 11 OSMesaGetProcAddress("gl" #F); 12 #define SK_GL_GET_PROC_SUFFIX(F, S) gBenchGL.f ## F = (BenchGL##F##Proc)\ 13 OSMesaGetProcAddress("gl" #F #S); 14 15 #elif defined(SK_BUILD_FOR_WIN32) 16 #define WIN32_LEAN_AND_MEAN 1 17 #include <Windows.h> 18 #include <GL/GL.h> 19 #define SK_BENCH_CONTEXT_CHECK (NULL != wglGetCurrentContext()) 20 21 #undef BENCH_GL_FUNCTION_TYPE 22 #define BENCH_GL_FUNCTION_TYPE __stdcall 23 24 #define SK_GL_GET_PROC(F) gBenchGL.f ## F = (BenchGL ## F ## Proc) \ 25 wglGetProcAddress("gl" #F); 26 #define SK_GL_GET_PROC_SUFFIX(F, S) gBenchGL.f ## F = (BenchGL##F##Proc)\ 27 wglGetProcAddress("gl" #F #S); 28 29 #elif defined(SK_BUILD_FOR_MAC) 30 #include <OpenGL/gl.h> 31 #include <OpenGL/CGLCurrent.h> 32 #define SK_BENCH_CONTEXT_CHECK (NULL != CGLGetCurrentContext()) 33 34 #elif defined(SK_BUILD_FOR_UNIX) 35 #include <GL/gl.h> 36 #include <GL/glx.h> 37 #define SK_BENCH_CONTEXT_CHECK (NULL != glXGetCurrentContext()) 38 39 #define SK_GL_GET_PROC(F) gBenchGL.f ## F = (BenchGL ## F ## Proc) \ 40 glXGetProcAddressARB(reinterpret_cast<const GLubyte*>("gl" #F)); 41 #define SK_GL_GET_PROC_SUFFIX(F, S) gBenchGL.f ## F = (BenchGL##F##Proc)\ 42 glXGetProcAddressARB(reinterpret_cast<const GLubyte*>("gl" #F #S)); 43 #else 44 #error unsupported platform 45 #endif 46 47 #define BenchGL_TIME_ELAPSED 0x88BF 48 #define BenchGL_QUERY_RESULT 0x8866 49 #define BenchGL_QUERY_RESULT_AVAILABLE 0x8867 50 51 #if defined(SK_BUILD_FOR_WIN32) 52 typedef UINT64 BenchGLuint64; 53 #else 54 #include <stdint.h> 55 typedef uint64_t BenchGLuint64; 56 #endif 57 58 typedef void (BENCH_GL_FUNCTION_TYPE *BenchGLGenQueriesProc) (GLsizei n, GLuint *ids); 59 typedef void (BENCH_GL_FUNCTION_TYPE *BenchGLBeginQueryProc) (GLenum target, GLuint id); 60 typedef void (BENCH_GL_FUNCTION_TYPE *BenchGLEndQueryProc) (GLenum target); 61 typedef void (BENCH_GL_FUNCTION_TYPE *BenchGLDeleteQueriesProc) (GLsizei n, const GLuint *ids); 62 typedef void (BENCH_GL_FUNCTION_TYPE *BenchGLGetQueryObjectivProc) (GLuint id, GLenum pname, GLint *params); 63 typedef void (BENCH_GL_FUNCTION_TYPE *BenchGLGetQueryObjectui64vProc) (GLuint id, GLenum pname, BenchGLuint64 *params); 64 65 struct BenchGLInterface { 66 bool fHasTimer; 67 BenchGLGenQueriesProc fGenQueries; 68 BenchGLBeginQueryProc fBeginQuery; 69 BenchGLEndQueryProc fEndQuery; 70 BenchGLDeleteQueriesProc fDeleteQueries; 71 BenchGLGetQueryObjectivProc fGetQueryObjectiv; 72 BenchGLGetQueryObjectui64vProc fGetQueryObjectui64v; 73 }; 74 75 static bool BenchGLCheckExtension(const char* ext, 76 const char* extensionString) { 77 int extLength = strlen(ext); 78 79 while (true) { 80 int n = strcspn(extensionString, " "); 81 if (n == extLength && 0 == strncmp(ext, extensionString, n)) { 82 return true; 83 } 84 if (0 == extensionString[n]) { 85 return false; 86 } 87 extensionString += n+1; 88 } 89 90 return false; 91 } 92 93 static BenchGLInterface gBenchGL; 94 static bool gBenchGLInterfaceInit = false; 95 96 static void BenchGLSetDefaultGLInterface() { 97 gBenchGL.fHasTimer = false; 98 if (gBenchGLInterfaceInit || !SK_BENCH_CONTEXT_CHECK) return; 99 100 const char* glExts = 101 reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); 102 const GLboolean ext = 103 BenchGLCheckExtension("GL_EXT_timer_query", glExts); 104 const GLboolean arb = 105 BenchGLCheckExtension("GL_ARB_timer_query", glExts); 106 if (ext || arb) { 107 #if defined(SK_BUILD_FOR_MAC) 108 #if GL_EXT_timer_query || GL_ARB_timer_query 109 gBenchGL.fHasTimer = true; 110 gBenchGL.fGenQueries = glGenQueries; 111 gBenchGL.fBeginQuery = glBeginQuery; 112 gBenchGL.fEndQuery = glEndQuery; 113 gBenchGL.fDeleteQueries = glDeleteQueries; 114 gBenchGL.fGetQueryObjectiv = glGetQueryObjectiv; 115 #endif 116 #if GL_ARB_timer_query 117 gBenchGL.fGetQueryObjectui64v = glGetQueryObjectui64v; 118 #elif GL_EXT_timer_query 119 gBenchGL.fGetQueryObjectui64v = glGetQueryObjectui64vEXT; 120 #endif 121 #else 122 gBenchGL.fHasTimer = true; 123 SK_GL_GET_PROC(GenQueries) 124 SK_GL_GET_PROC(BeginQuery) 125 SK_GL_GET_PROC(EndQuery) 126 SK_GL_GET_PROC(DeleteQueries) 127 128 SK_GL_GET_PROC(GetQueryObjectiv) 129 if (arb) { 130 SK_GL_GET_PROC(GetQueryObjectui64v) 131 } else { 132 SK_GL_GET_PROC_SUFFIX(GetQueryObjectui64v, EXT) 133 } 134 #endif 135 } 136 gBenchGLInterfaceInit = true; 137 } 138 139 BenchGpuTimer::BenchGpuTimer() { 140 BenchGLSetDefaultGLInterface(); 141 if (gBenchGL.fHasTimer) { 142 gBenchGL.fGenQueries(1, &this->fQuery); 143 } 144 } 145 146 BenchGpuTimer::~BenchGpuTimer() { 147 if (gBenchGL.fHasTimer) { 148 gBenchGL.fDeleteQueries(1, &this->fQuery); 149 } 150 } 151 152 void BenchGpuTimer::startGpu() { 153 if (!gBenchGL.fHasTimer) return; 154 155 this->fStarted = true; 156 gBenchGL.fBeginQuery(BenchGL_TIME_ELAPSED, this->fQuery); 157 } 158 159 /** 160 * It is important to stop the cpu clocks first, 161 * as this will cpu wait for the gpu to finish. 162 */ 163 double BenchGpuTimer::endGpu() { 164 if (!gBenchGL.fHasTimer) return 0; 165 166 this->fStarted = false; 167 gBenchGL.fEndQuery(BenchGL_TIME_ELAPSED); 168 169 GLint available = 0; 170 while (!available) { 171 gBenchGL.fGetQueryObjectiv(this->fQuery 172 , BenchGL_QUERY_RESULT_AVAILABLE 173 , &available); 174 } 175 BenchGLuint64 totalGPUTimeElapsed = 0; 176 gBenchGL.fGetQueryObjectui64v(this->fQuery 177 , BenchGL_QUERY_RESULT 178 , &totalGPUTimeElapsed); 179 180 return totalGPUTimeElapsed / 1000000.0; 181 } 182