diff options
author | bungeman@google.com <bungeman@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-06-07 19:16:02 +0000 |
---|---|---|
committer | bungeman@google.com <bungeman@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-06-07 19:16:02 +0000 |
commit | be9ad4e5fc6126a1273a7dccf1a85db72e763df3 (patch) | |
tree | c2cbcb82171d33e7034116891d6f6f70c6448537 /bench | |
parent | 41249466fe997f9df3fec3c06e03d56fc48be607 (diff) |
Higher resolution timers for bench.
http://codereview.appspot.com/4548090/
git-svn-id: http://skia.googlecode.com/svn/trunk@1534 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'bench')
-rw-r--r-- | bench/BenchGpuTimer_gl.cpp | 181 | ||||
-rw-r--r-- | bench/BenchGpuTimer_gl.h | 33 | ||||
-rw-r--r-- | bench/BenchGpuTimer_none.cpp | 13 | ||||
-rw-r--r-- | bench/BenchGpuTimer_none.h | 12 | ||||
-rw-r--r-- | bench/BenchSysTimer_c.cpp | 20 | ||||
-rw-r--r-- | bench/BenchSysTimer_c.h | 19 | ||||
-rw-r--r-- | bench/BenchSysTimer_mach.cpp | 69 | ||||
-rw-r--r-- | bench/BenchSysTimer_mach.h | 19 | ||||
-rw-r--r-- | bench/BenchSysTimer_posix.cpp | 50 | ||||
-rw-r--r-- | bench/BenchSysTimer_posix.h | 19 | ||||
-rw-r--r-- | bench/BenchSysTimer_windows.cpp | 55 | ||||
-rw-r--r-- | bench/BenchSysTimer_windows.h | 19 | ||||
-rw-r--r-- | bench/BenchTimer.cpp | 48 | ||||
-rw-r--r-- | bench/BenchTimer.h | 27 | ||||
-rw-r--r-- | bench/benchmain.cpp | 46 |
15 files changed, 621 insertions, 9 deletions
diff --git a/bench/BenchGpuTimer_gl.cpp b/bench/BenchGpuTimer_gl.cpp new file mode 100644 index 0000000000..ec2145d821 --- /dev/null +++ b/bench/BenchGpuTimer_gl.cpp @@ -0,0 +1,181 @@ +#include "BenchGpuTimer_gl.h" +#include <string.h> + +//GL +#define BENCH_GL_FUNCTION_TYPE +#if defined(SK_MESA) + #include <GL/osmesa.h> + #define SK_BENCH_CONTEXT_CHECK (NULL != OSMesaGetCurrentContext()) + + #define SK_GL_GET_PROC(F) gBenchGL.f ## F = (BenchGL ## F ## Proc) \ + OSMesaGetProcAddress("gl" #F); + #define SK_GL_GET_PROC_SUFFIX(F, S) gBenchGL.f ## F = (BenchGL##F##Proc)\ + OSMesaGetProcAddress("gl" #F #S); + +#elif defined(SK_BUILD_FOR_WIN32) + #define WIN32_LEAN_AND_MEAN 1 + #include <Windows.h> + #include <GL/GL.h> + #define SK_BENCH_CONTEXT_CHECK (NULL != wglGetCurrentContext()) + + #undef BENCH_GL_FUNCTION_TYPE + #define BENCH_GL_FUNCTION_TYPE __stdcall + + #define SK_GL_GET_PROC(F) gBenchGL.f ## F = (BenchGL ## F ## Proc) \ + wglGetProcAddress("gl" #F); + #define SK_GL_GET_PROC_SUFFIX(F, S) gBenchGL.f ## F = (BenchGL##F##Proc)\ + wglGetProcAddress("gl" #F #S); + +#elif defined(SK_BUILD_FOR_MAC) + #include <OpenGL/gl.h> + #include <OpenGL/CGLCurrent.h> + #define SK_BENCH_CONTEXT_CHECK (NULL != CGLGetCurrentContext()) + +#elif defined(SK_BUILD_FOR_UNIX) + #include <GL/gl.h> + #include <GL/glx.h> + #define SK_BENCH_CONTEXT_CHECK (NULL != glXGetCurrentContext()) + + #define SK_GL_GET_PROC(F) gBenchGL.f ## F = (BenchGL ## F ## Proc) \ + glXGetProcAddressARB(reinterpret_cast<const GLubyte*>("gl" #F)); + #define SK_GL_GET_PROC_SUFFIX(F, S) gBenchGL.f ## F = (BenchGL##F##Proc)\ + glXGetProcAddressARB(reinterpret_cast<const GLubyte*>("gl" #F #S)); +#else + #error unsupported platform +#endif + +#define BenchGL_TIME_ELAPSED 0x88BF +#define BenchGL_QUERY_RESULT 0x8866 +#define BenchGL_QUERY_RESULT_AVAILABLE 0x8867 + +#if defined(SK_BUILD_FOR_WIN32) +typedef UINT64 BenchGLuint64; +#else +#include <stdint.h> +typedef uint64_t BenchGLuint64; +#endif + +typedef void (BENCH_GL_FUNCTION_TYPE *BenchGLGenQueriesProc) (GLsizei n, GLuint *ids); +typedef void (BENCH_GL_FUNCTION_TYPE *BenchGLBeginQueryProc) (GLenum target, GLuint id); +typedef void (BENCH_GL_FUNCTION_TYPE *BenchGLEndQueryProc) (GLenum target); +typedef void (BENCH_GL_FUNCTION_TYPE *BenchGLDeleteQueriesProc) (GLsizei n, const GLuint *ids); +typedef void (BENCH_GL_FUNCTION_TYPE *BenchGLGetQueryObjectivProc) (GLuint id, GLenum pname, GLint *params); +typedef void (BENCH_GL_FUNCTION_TYPE *BenchGLGetQueryObjectui64vProc) (GLuint id, GLenum pname, BenchGLuint64 *params); + +struct BenchGLInterface { + bool fHasTimer; + BenchGLGenQueriesProc fGenQueries; + BenchGLBeginQueryProc fBeginQuery; + BenchGLEndQueryProc fEndQuery; + BenchGLDeleteQueriesProc fDeleteQueries; + BenchGLGetQueryObjectivProc fGetQueryObjectiv; + BenchGLGetQueryObjectui64vProc fGetQueryObjectui64v; +}; + +static bool BenchGLCheckExtension(const char* ext, + const char* extensionString) { + int extLength = strlen(ext); + + while (true) { + int n = strcspn(extensionString, " "); + if (n == extLength && 0 == strncmp(ext, extensionString, n)) { + return true; + } + if (0 == extensionString[n]) { + return false; + } + extensionString += n+1; + } + + return false; +} + +static BenchGLInterface gBenchGL; +static bool gBenchGLInterfaceInit = false; + +static void BenchGLSetDefaultGLInterface() { + gBenchGL.fHasTimer = false; + if (gBenchGLInterfaceInit || !SK_BENCH_CONTEXT_CHECK) return; + + const char* glExts = + reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); + const GLboolean ext = + BenchGLCheckExtension("GL_EXT_timer_query", glExts); + const GLboolean arb = + BenchGLCheckExtension("GL_ARB_timer_query", glExts); + if (ext || arb) { +#if defined(SK_BUILD_FOR_MAC) + #if GL_EXT_timer_query || GL_ARB_timer_query + gBenchGL.fHasTimer = true; + gBenchGL.fGenQueries = glGenQueries; + gBenchGL.fBeginQuery = glBeginQuery; + gBenchGL.fEndQuery = glEndQuery; + gBenchGL.fDeleteQueries = glDeleteQueries; + gBenchGL.fGetQueryObjectiv = glGetQueryObjectiv; + #endif + #if GL_ARB_timer_query + gBenchGL.fGetQueryObjectui64v = glGetQueryObjectui64v; + #elif GL_EXT_timer_query + gBenchGL.fGetQueryObjectui64v = glGetQueryObjectui64vEXT; + #endif +#else + gBenchGL.fHasTimer = true; + SK_GL_GET_PROC(GenQueries) + SK_GL_GET_PROC(BeginQuery) + SK_GL_GET_PROC(EndQuery) + SK_GL_GET_PROC(DeleteQueries) + + SK_GL_GET_PROC(GetQueryObjectiv) + if (arb) { + SK_GL_GET_PROC(GetQueryObjectui64v) + } else { + SK_GL_GET_PROC_SUFFIX(GetQueryObjectui64v, EXT) + } +#endif + } + gBenchGLInterfaceInit = true; +} + +BenchGpuTimer::BenchGpuTimer() { + BenchGLSetDefaultGLInterface(); + if (gBenchGL.fHasTimer) { + gBenchGL.fGenQueries(1, &this->fQuery); + } +} + +BenchGpuTimer::~BenchGpuTimer() { + if (gBenchGL.fHasTimer) { + gBenchGL.fDeleteQueries(1, &this->fQuery); + } +} + +void BenchGpuTimer::startGpu() { + if (!gBenchGL.fHasTimer) return; + + this->fStarted = true; + gBenchGL.fBeginQuery(BenchGL_TIME_ELAPSED, this->fQuery); +} + +/** + * It is important to stop the cpu clocks first, + * as this will cpu wait for the gpu to finish. + */ +double BenchGpuTimer::endGpu() { + if (!gBenchGL.fHasTimer) return 0; + + this->fStarted = false; + gBenchGL.fEndQuery(BenchGL_TIME_ELAPSED); + + GLint available = 0; + while (!available) { + gBenchGL.fGetQueryObjectiv(this->fQuery + , BenchGL_QUERY_RESULT_AVAILABLE + , &available); + } + BenchGLuint64 totalGPUTimeElapsed = 0; + gBenchGL.fGetQueryObjectui64v(this->fQuery + , BenchGL_QUERY_RESULT + , &totalGPUTimeElapsed); + + return totalGPUTimeElapsed / 1000000.0; +} diff --git a/bench/BenchGpuTimer_gl.h b/bench/BenchGpuTimer_gl.h new file mode 100644 index 0000000000..ac2348274a --- /dev/null +++ b/bench/BenchGpuTimer_gl.h @@ -0,0 +1,33 @@ +#ifndef SkBenchGpuTimer_DEFINED +#define SkBenchGpuTimer_DEFINED + +#if defined(SK_MESA) + #include <GL/osmesa.h> + +#elif defined(SK_BUILD_FOR_WIN32) + #define WIN32_LEAN_AND_MEAN 1 + #include <Windows.h> + #include <GL/GL.h> + +#elif defined(SK_BUILD_FOR_MAC) + #include <OpenGL/gl.h> + +#elif defined(SK_BUILD_FOR_UNIX) + #include <GL/gl.h> + +#else + #error unsupported platform +#endif + +class BenchGpuTimer { +public: + BenchGpuTimer(); + ~BenchGpuTimer(); + void startGpu(); + double endGpu(); +private: + GLuint fQuery; + int fStarted; +}; + +#endif diff --git a/bench/BenchGpuTimer_none.cpp b/bench/BenchGpuTimer_none.cpp new file mode 100644 index 0000000000..4ead4acc7f --- /dev/null +++ b/bench/BenchGpuTimer_none.cpp @@ -0,0 +1,13 @@ +#include "BenchGpuTimer_none.h" + +BenchGpuTimer::BenchGpuTimer() { +} + +BenchTimer::~BenchTimer() { +} + +void BenchTimer::startGpu() { +} + +void BenchTimer::endGpu() { +} diff --git a/bench/BenchGpuTimer_none.h b/bench/BenchGpuTimer_none.h new file mode 100644 index 0000000000..7069ca485b --- /dev/null +++ b/bench/BenchGpuTimer_none.h @@ -0,0 +1,12 @@ +#ifndef SkBenchGpuTimer_DEFINED +#define SkBenchGpuTimer_DEFINED + +class BenchGpuTimer { +public: + BenchGpuTimer(); + ~BenchGpuTimer(); + void startGpu(); + double endGpu(); +}; + +#endif diff --git a/bench/BenchSysTimer_c.cpp b/bench/BenchSysTimer_c.cpp new file mode 100644 index 0000000000..fc0850baef --- /dev/null +++ b/bench/BenchSysTimer_c.cpp @@ -0,0 +1,20 @@ +#include "BenchSysTimer_c.h" + +//Time +#include <time.h> + +void BenchSysTimer::startWall() { + this->fStartWall = time(); +} +void BenchSysTimer::startCpu() { + this->fStartCpu = clock(); +} + +double BenchSysTimer::endCpu() { + clock_t end_cpu = clock(); + this->fCpu = (end_cpu - this->fStartCpu) * CLOCKS_PER_SEC / 1000.0; +} +double BenchSysTimer::endWall() { + time_t end_wall = time(); + this->fWall = difftime(end_wall, this->fstartWall) / 1000.0; +} diff --git a/bench/BenchSysTimer_c.h b/bench/BenchSysTimer_c.h new file mode 100644 index 0000000000..c598f3097b --- /dev/null +++ b/bench/BenchSysTimer_c.h @@ -0,0 +1,19 @@ +#ifndef SkBenchSysTimer_DEFINED +#define SkBenchSysTimer_DEFINED + +//Time +#include <time.h> +#warning standard clocks + +class BenchSysTimer { +public: + void startWall(); + void startCpu(); + double endCpu(); + double endWall(); +private: + clock_t start_cpu; + time_t fStartWall; +}; + +#endif diff --git a/bench/BenchSysTimer_mach.cpp b/bench/BenchSysTimer_mach.cpp new file mode 100644 index 0000000000..b23897ce1c --- /dev/null +++ b/bench/BenchSysTimer_mach.cpp @@ -0,0 +1,69 @@ +#include "BenchSysTimer_mach.h" + +//Time +#include <mach/mach.h> +#include <mach/mach_time.h> + +static time_value_t macCpuTime() { + mach_port_t task = mach_task_self(); + if (task == MACH_PORT_NULL) { + time_value_t none = {0, 0}; + return none; + } + + task_thread_times_info thread_info_data; + mach_msg_type_number_t thread_info_count = TASK_THREAD_TIMES_INFO_COUNT; + if (KERN_SUCCESS != task_info(task, + TASK_THREAD_TIMES_INFO, + reinterpret_cast<task_info_t>(&thread_info_data), + &thread_info_count)) + { + time_value_t none = {0, 0}; + return none; + } + + time_value_add(&thread_info_data.user_time, &thread_info_data.system_time) + return thread_info_data.user_time; +} + +static double intervalInMSec(const time_value_t start_clock + , const time_value_t end_clock) +{ + double duration_clock; + if ((end_clock.microseconds - start_clock.microseconds) < 0) { + duration_clock = (end_clock.seconds - start_clock.seconds-1)*1000; + duration_clock += (1000000 + + end_clock.microseconds + - start_clock.microseconds) / 1000.0; + } else { + duration_clock = (end_clock.seconds - start_clock.seconds)*1000; + duration_clock += (end_clock.microseconds - start_clock.microseconds) + / 1000.0; + } + return duration_clock; +} + +void BenchSysTimer::startWall() { + this->fStartWall = mach_absolute_time(); +} +void BenchSysTimer::startCpu() { + this->fStartCpu = macCpuTime(); +} + +double BenchSysTimer::endCpu() { + time_value_t end_cpu = macCpuTime(); + return intervalInMSec(this->fStartCpu, end_cpu); +} +double BenchSysTimer::endWall() { + uint64_t end_wall = mach_absolute_time(); + + uint64_t elapsed = end_wall - this->fStartWall; + mach_timebase_info_data_t sTimebaseInfo; + if (KERN_SUCCESS != mach_timebase_info(&sTimebaseInfo)) { + return 0; + } else { + uint64_t elapsedNano = elapsed * sTimebaseInfo.numer + / sTimebaseInfo.denom; + return elapsedNano / 1000000; + } +} diff --git a/bench/BenchSysTimer_mach.h b/bench/BenchSysTimer_mach.h new file mode 100644 index 0000000000..da4fff0790 --- /dev/null +++ b/bench/BenchSysTimer_mach.h @@ -0,0 +1,19 @@ +#ifndef SkBenchSysTimer_DEFINED +#define SkBenchSysTimer_DEFINED + +//Time +#include <mach/mach.h> +#include <mach/mach_time.h> + +class BenchSysTimer { +public: + void startWall(); + void startCpu(); + double endCpu(); + double endWall(); +private: + time_value_t fStartCpu; + uint64_t fStartWall; +}; + +#endif diff --git a/bench/BenchSysTimer_posix.cpp b/bench/BenchSysTimer_posix.cpp new file mode 100644 index 0000000000..5d28f40f2e --- /dev/null +++ b/bench/BenchSysTimer_posix.cpp @@ -0,0 +1,50 @@ +#include "BenchSysTimer_posix.h" + +//Time +#include <time.h> + +static double intervalInMSec(const timespec start_clock + , const timespec end_clock) +{ + double duration_clock; + if ((end_clock.tv_nsec - start_clock.tv_nsec) < 0) { + duration_clock = (end_clock.tv_sec - start_clock.tv_sec-1)*1000; + duration_clock += (1000000000 + end_clock.tv_nsec - start_clock.tv_nsec) + / 1000000.0; + } else { + duration_clock = (end_clock.tv_sec - start_clock.tv_sec)*1000; + duration_clock += (end_clock.tv_nsec - start_clock.tv_nsec) / 1000000.0; + } + return duration_clock; +} + +void BenchSysTimer::startWall() { + if (-1 == clock_gettime(CLOCK_MONOTONIC, &this->fWall)) { + timespec none = {0, 0}; + this->fWall = none; + } +} +void BenchSysTimer::startCpu() { + if (-1 == clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &this->fCpu)) { + timespec none = {0, 0}; + this->fCpu = none; + } +} + +double BenchSysTimer::endCpu() { + timespec end_cpu; + if (-1 == clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end_cpu)) { + timespec none = {0, 0}; + end_cpu = none; + } + return intervalInMSec(this->fCpu, end_cpu); +} + +double BenchSysTimer::endWall() { + timespec end_wall; + if (-1 == clock_gettime(CLOCK_MONOTONIC, &end_wall)) { + timespec none = {0, 0}; + end_wall = none; + } + return intervalInMSec(this->fWall, end_wall); +} diff --git a/bench/BenchSysTimer_posix.h b/bench/BenchSysTimer_posix.h new file mode 100644 index 0000000000..09dfb0e142 --- /dev/null +++ b/bench/BenchSysTimer_posix.h @@ -0,0 +1,19 @@ +#ifndef SkBenchSysTimer_DEFINED +#define SkBenchSysTimer_DEFINED + +//Time +#include <time.h> + +class BenchSysTimer { +public: + void startWall(); + void startCpu(); + double endCpu(); + double endWall(); +private: + timespec fCpu; + timespec fWall; +}; + +#endif + diff --git a/bench/BenchSysTimer_windows.cpp b/bench/BenchSysTimer_windows.cpp new file mode 100644 index 0000000000..923754c264 --- /dev/null +++ b/bench/BenchSysTimer_windows.cpp @@ -0,0 +1,55 @@ +#include "BenchSysTimer_windows.h" + +//Time +#define WIN32_LEAN_AND_MEAN 1 +#include <Windows.h> + +static ULONGLONG winCpuTime() { + FILETIME createTime; + FILETIME exitTime; + FILETIME usrTime; + FILETIME sysTime; + if (0 == GetProcessTimes(GetCurrentProcess() + , &createTime, &exitTime + , &sysTime, &usrTime)) + { + return 0; + } + ULARGE_INTEGER start_cpu_sys; + ULARGE_INTEGER start_cpu_usr; + start_cpu_sys.LowPart = sysTime.dwLowDateTime; + start_cpu_sys.HighPart = sysTime.dwHighDateTime; + start_cpu_usr.LowPart = usrTime.dwLowDateTime; + start_cpu_usr.HighPart = usrTime.dwHighDateTime; + return start_cpu_sys.QuadPart + start_cpu_usr.QuadPart; +} + +void BenchSysTimer::startWall() { + if (0 == ::QueryPerformanceCounter(&this->fStartWall)) { + this->fStartWall.QuadPart = 0; + } +} +void BenchSysTimer::startCpu() { + this->fStartCpu = winCpuTime(); +} + +double BenchSysTimer::endCpu() { + ULONGLONG end_cpu = winCpuTime(); + return (end_cpu - this->fStartCpu) / 10000; +} +double BenchSysTimer::endWall() { + LARGE_INTEGER end_wall; + if (0 == ::QueryPerformanceCounter(&end_wall)) { + end_wall.QuadPart = 0; + } + + LARGE_INTEGER ticks_elapsed; + ticks_elapsed.QuadPart = end_wall.QuadPart - this->fStartWall.QuadPart; + + LARGE_INTEGER frequency; + if (0 == ::QueryPerformanceFrequency(&frequency)) { + return 0; + } else { + return (double)ticks_elapsed.QuadPart / frequency.QuadPart * 1000; + } +} diff --git a/bench/BenchSysTimer_windows.h b/bench/BenchSysTimer_windows.h new file mode 100644 index 0000000000..72a3fb2e79 --- /dev/null +++ b/bench/BenchSysTimer_windows.h @@ -0,0 +1,19 @@ +#ifndef SkBenchSysTimer_DEFINED +#define SkBenchSysTimer_DEFINED + +//Time +#define WIN32_LEAN_AND_MEAN 1 +#include <Windows.h> + +struct BenchSysTimer { +public: + void startWall(); + void startCpu(); + double endCpu(); + double endWall(); +private: + ULONGLONG fStartCpu; + LARGE_INTEGER fStartWall; +}; + +#endif diff --git a/bench/BenchTimer.cpp b/bench/BenchTimer.cpp new file mode 100644 index 0000000000..e7b0068ac4 --- /dev/null +++ b/bench/BenchTimer.cpp @@ -0,0 +1,48 @@ +#include "BenchTimer.h" +#if defined(SK_BUILD_FOR_WIN32) + #include "BenchSysTimer_windows.h" +#elif defined(SK_BUILD_FOR_MAC) + #include "BenchSysTimer_mach.h" +#elif defined(SK_BUILD_FOR_UNIX) + #include "BenchSysTimer_posix.h" +#else + #include "BenchSysTimer_c.h" +#endif + +#if defined(SK_MESA) || \ + defined(SK_BUILD_FOR_WIN32) || \ + defined(SK_BUILD_FOR_MAC) || \ + defined(SK_BUILD_FOR_UNIX) + #include "BenchGpuTimer_gl.h" + +#else + #include "BenchGpuTimer_none.h" +#endif + +BenchTimer::BenchTimer() + : fCpu(-1.0) + , fWall(-1.0) + , fGpu(-1.0) +{ + this->fSysTimer = new BenchSysTimer(); + this->fGpuTimer = new BenchGpuTimer(); +} + +BenchTimer::~BenchTimer() { + delete this->fSysTimer; + delete this->fGpuTimer; +} + +void BenchTimer::start() { + this->fSysTimer->startWall(); + this->fGpuTimer->startGpu(); + this->fSysTimer->startCpu(); +} + +void BenchTimer::end() { + this->fCpu = this->fSysTimer->endCpu(); + //It is important to stop the cpu clocks first, + //as the following will cpu wait for the gpu to finish. + this->fGpu = this->fGpuTimer->endGpu(); + this->fWall = this->fSysTimer->endWall(); +} diff --git a/bench/BenchTimer.h b/bench/BenchTimer.h new file mode 100644 index 0000000000..eae82d5f29 --- /dev/null +++ b/bench/BenchTimer.h @@ -0,0 +1,27 @@ +#ifndef SkBenchTimer_DEFINED +#define SkBenchTimer_DEFINED + +class BenchSysTimer; +class BenchGpuTimer; + +/** + * SysTimers and GpuTimers are implemented orthogonally. + * This class combines a SysTimer and a GpuTimer into one single, + * platform specific, Timer with a simple interface. + */ +class BenchTimer { +public: + BenchTimer(); + ~BenchTimer(); + void start(); + void end(); + double fCpu; + double fWall; + double fGpu; + +private: + BenchSysTimer *fSysTimer; + BenchGpuTimer *fGpuTimer; +}; + +#endif diff --git a/bench/benchmain.cpp b/bench/benchmain.cpp index 066573aee9..34f8a1a9fa 100644 --- a/bench/benchmain.cpp +++ b/bench/benchmain.cpp @@ -5,12 +5,12 @@ #include "SkNWayCanvas.h" #include "SkPicture.h" #include "SkString.h" -#include "SkTime.h" #include "GrContext.h" #include "SkGpuDevice.h" #include "SkEGLContext.h" #include "SkBenchmark.h" +#include "BenchTimer.h" #ifdef ANDROID static void log_error(const char msg[]) { SkDebugf("%s", msg); } @@ -212,6 +212,9 @@ int main (int argc, char * const argv[]) { bool forceAA = true; bool forceFilter = false; SkTriState::State forceDither = SkTriState::kDefault; + bool timerWall = false; + bool timerCpu = true; + bool timerGpu = true; bool doScale = false; bool doRotate = false; bool doClip = false; @@ -246,6 +249,23 @@ int main (int argc, char * const argv[]) { log_error("missing arg for -repeat\n"); return -1; } + } else if (strcmp(*argv, "-timers") == 0) { + argv++; + if (argv < stop) { + timerWall = false; + timerCpu = false; + timerGpu = false; + for (char* t = *argv; *t; ++t) { + switch (*t) { + case 'w': timerWall = true; break; + case 'c': timerCpu = true; break; + case 'g': timerGpu = true; break; + } + } + } else { + log_error("missing arg for -timers\n"); + return -1; + } } else if (!strcmp(*argv, "-rotate")) { doRotate = true; } else if (!strcmp(*argv, "-scale")) { @@ -346,6 +366,8 @@ int main (int argc, char * const argv[]) { context = GrContext::CreateGLShaderContext(); } + BenchTimer timer = BenchTimer(); + Iter iter(&defineDict); SkBenchmark* bench; while ((bench = iter.next()) != NULL) { @@ -399,30 +421,36 @@ int main (int argc, char * const argv[]) { performRotate(&canvas, dim.fX, dim.fY); } + bool gpu = kGPU_Backend == backend && context; //warm up caches if needed if (repeatDraw > 1) { SkAutoCanvasRestore acr(&canvas, true); bench->draw(&canvas); - if (kGPU_Backend == backend && context) { + if (gpu) { context->flush(); glFinish(); } } - SkMSec now = SkTime::GetMSecs(); + timer.start(); for (int i = 0; i < repeatDraw; i++) { SkAutoCanvasRestore acr(&canvas, true); bench->draw(&canvas); } - if (kGPU_Backend == backend && context) { - context->flush(); - glFinish(); - } + timer.end(); if (repeatDraw > 1) { - double duration = SkTime::GetMSecs() - now; SkString str; - str.printf(" %4s: msecs = %5.2f", configName, duration / repeatDraw); + str.printf(" %4s:", configName); + if (timerWall) { + str.appendf(" msecs = %6.2f", timer.fWall / repeatDraw); + } + if (timerCpu) { + str.appendf(" cmsecs = %6.2f", timer.fCpu / repeatDraw); + } + if (timerGpu && gpu && timer.fGpu > 0) { + str.appendf(" gmsecs = %6.2f", timer.fGpu / repeatDraw); + } log_progress(str); } if (outDir.size() > 0) { |