• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
BenchGLCheckExtension(const char * ext,const char * extensionString)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 
BenchGLSetDefaultGLInterface()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 
BenchGpuTimer()139 BenchGpuTimer::BenchGpuTimer() {
140     BenchGLSetDefaultGLInterface();
141     if (gBenchGL.fHasTimer) {
142         gBenchGL.fGenQueries(1, &this->fQuery);
143     }
144 }
145 
~BenchGpuTimer()146 BenchGpuTimer::~BenchGpuTimer() {
147     if (gBenchGL.fHasTimer) {
148         gBenchGL.fDeleteQueries(1, &this->fQuery);
149     }
150 }
151 
startGpu()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  */
endGpu()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