Home | History | Annotate | Download | only in bench
      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