| Index: tools/gpu/gl/GLTestContext.cpp
|
| diff --git a/tools/gpu/gl/GLTestContext.cpp b/tools/gpu/gl/GLTestContext.cpp
|
| index 1b077d5a022facd9d12755acc9bc4479fadf2702..20a99083810be034556d2fbddce92b357ca3dbbc 100644
|
| --- a/tools/gpu/gl/GLTestContext.cpp
|
| +++ b/tools/gpu/gl/GLTestContext.cpp
|
| @@ -6,6 +6,8 @@
|
| */
|
|
|
| #include "GLTestContext.h"
|
| +
|
| +#include "GpuTimer.h"
|
| #include "gl/GrGLUtil.h"
|
|
|
| namespace {
|
| @@ -78,6 +80,135 @@ void GLFenceSync::deleteFence(sk_gpu_test::PlatformFence fence) const {
|
| fGLDeleteSync(glsync);
|
| }
|
|
|
| +class GLGpuTimer : public sk_gpu_test::GpuTimer {
|
| +public:
|
| + static GLGpuTimer* CreateIfSupported(const sk_gpu_test::GLTestContext*);
|
| +
|
| + QueryStatus checkQueryStatus(sk_gpu_test::PlatformTimerQuery) override;
|
| + std::chrono::nanoseconds getTimeElapsed(sk_gpu_test::PlatformTimerQuery) override;
|
| + void deleteQuery(sk_gpu_test::PlatformTimerQuery) override;
|
| +
|
| +private:
|
| + GLGpuTimer(bool disjointSupport, const sk_gpu_test::GLTestContext*, const char* ext = "");
|
| +
|
| + bool validate() const;
|
| +
|
| + sk_gpu_test::PlatformTimerQuery onQueueTimerStart() const override;
|
| + void onQueueTimerStop(sk_gpu_test::PlatformTimerQuery) const override;
|
| +
|
| + static constexpr GrGLenum GL_QUERY_RESULT = 0x8866;
|
| + static constexpr GrGLenum GL_QUERY_RESULT_AVAILABLE = 0x8867;
|
| + static constexpr GrGLenum GL_TIME_ELAPSED = 0x88bf;
|
| + static constexpr GrGLenum GL_GPU_DISJOINT = 0x8fbb;
|
| +
|
| + typedef void (GR_GL_FUNCTION_TYPE* GLGetIntegervProc) (GrGLenum, GrGLint*);
|
| + typedef void (GR_GL_FUNCTION_TYPE* GLGenQueriesProc) (GrGLsizei, GrGLuint*);
|
| + typedef void (GR_GL_FUNCTION_TYPE* GLDeleteQueriesProc) (GrGLsizei, const GrGLuint*);
|
| + typedef void (GR_GL_FUNCTION_TYPE* GLBeginQueryProc) (GrGLenum, GrGLuint);
|
| + typedef void (GR_GL_FUNCTION_TYPE* GLEndQueryProc) (GrGLenum);
|
| + typedef void (GR_GL_FUNCTION_TYPE* GLGetQueryObjectuivProc) (GrGLuint, GrGLenum, GrGLuint*);
|
| + typedef void (GR_GL_FUNCTION_TYPE* GLGetQueryObjectui64vProc) (GrGLuint, GrGLenum, GrGLuint64*);
|
| +
|
| + GLGetIntegervProc fGLGetIntegerv;
|
| + GLGenQueriesProc fGLGenQueries;
|
| + GLDeleteQueriesProc fGLDeleteQueries;
|
| + GLBeginQueryProc fGLBeginQuery;
|
| + GLEndQueryProc fGLEndQuery;
|
| + GLGetQueryObjectuivProc fGLGetQueryObjectuiv;
|
| + GLGetQueryObjectui64vProc fGLGetQueryObjectui64v;
|
| +
|
| +
|
| + typedef sk_gpu_test::GpuTimer INHERITED;
|
| +};
|
| +
|
| +GLGpuTimer* GLGpuTimer::CreateIfSupported(const sk_gpu_test::GLTestContext* ctx) {
|
| + SkAutoTDelete<GLGpuTimer> ret;
|
| + const GrGLInterface* gl = ctx->gl();
|
| + if (gl->fExtensions.has("GL_EXT_disjoint_timer_query")) {
|
| + ret.reset(new GLGpuTimer(true, ctx, "EXT"));
|
| + } else if (kGL_GrGLStandard == gl->fStandard &&
|
| + (GrGLGetVersion(gl) > GR_GL_VER(3,3) || gl->fExtensions.has("GL_ARB_timer_query"))) {
|
| + ret.reset(new GLGpuTimer(false, ctx));
|
| + } else if (gl->fExtensions.has("GL_EXT_timer_query")) {
|
| + ret.reset(new GLGpuTimer(false, ctx, "EXT"));
|
| + }
|
| + return ret && ret->validate() ? ret.release() : nullptr;
|
| +}
|
| +
|
| +GLGpuTimer::GLGpuTimer(bool disjointSupport, const sk_gpu_test::GLTestContext* ctx, const char* ext)
|
| + : INHERITED(disjointSupport) {
|
| + ctx->getGLProcAddress(&fGLGetIntegerv, "glGetIntegerv");
|
| + ctx->getGLProcAddress(&fGLGenQueries, "glGenQueries", ext);
|
| + ctx->getGLProcAddress(&fGLDeleteQueries, "glDeleteQueries", ext);
|
| + ctx->getGLProcAddress(&fGLBeginQuery, "glBeginQuery", ext);
|
| + ctx->getGLProcAddress(&fGLEndQuery, "glEndQuery", ext);
|
| + ctx->getGLProcAddress(&fGLGetQueryObjectuiv, "glGetQueryObjectuiv", ext);
|
| + ctx->getGLProcAddress(&fGLGetQueryObjectui64v, "glGetQueryObjectui64v", ext);
|
| +}
|
| +
|
| +bool GLGpuTimer::validate() const {
|
| + return fGLGetIntegerv && fGLGenQueries && fGLDeleteQueries && fGLBeginQuery && fGLEndQuery &&
|
| + fGLGetQueryObjectuiv && fGLGetQueryObjectui64v;
|
| +}
|
| +
|
| +sk_gpu_test::PlatformTimerQuery GLGpuTimer::onQueueTimerStart() const {
|
| + GrGLuint queryID;
|
| + fGLGenQueries(1, &queryID);
|
| + if (!queryID) {
|
| + return sk_gpu_test::kInvalidTimerQuery;
|
| + }
|
| + if (this->disjointSupport()) {
|
| + // Clear the disjoint flag.
|
| + GrGLint disjoint;
|
| + fGLGetIntegerv(GL_GPU_DISJOINT, &disjoint);
|
| + }
|
| + fGLBeginQuery(GL_TIME_ELAPSED, queryID);
|
| + return static_cast<sk_gpu_test::PlatformTimerQuery>(queryID);
|
| +}
|
| +
|
| +void GLGpuTimer::onQueueTimerStop(sk_gpu_test::PlatformTimerQuery platformTimer) const {
|
| + if (sk_gpu_test::kInvalidTimerQuery == platformTimer) {
|
| + return;
|
| + }
|
| + fGLEndQuery(GL_TIME_ELAPSED);
|
| +}
|
| +
|
| +sk_gpu_test::GpuTimer::QueryStatus
|
| +GLGpuTimer::checkQueryStatus(sk_gpu_test::PlatformTimerQuery platformTimer) {
|
| + const GrGLuint queryID = static_cast<GrGLuint>(platformTimer);
|
| + if (!queryID) {
|
| + return QueryStatus::kInvalid;
|
| + }
|
| + GrGLuint available = 0;
|
| + fGLGetQueryObjectuiv(queryID, GL_QUERY_RESULT_AVAILABLE, &available);
|
| + if (!available) {
|
| + return QueryStatus::kPending;
|
| + }
|
| + if (this->disjointSupport()) {
|
| + GrGLint disjoint = 1;
|
| + fGLGetIntegerv(GL_GPU_DISJOINT, &disjoint);
|
| + if (disjoint) {
|
| + return QueryStatus::kDisjoint;
|
| + }
|
| + }
|
| + return QueryStatus::kAccurate;
|
| +}
|
| +
|
| +std::chrono::nanoseconds GLGpuTimer::getTimeElapsed(sk_gpu_test::PlatformTimerQuery platformTimer) {
|
| + SkASSERT(this->checkQueryStatus(platformTimer) >= QueryStatus::kDisjoint);
|
| + const GrGLuint queryID = static_cast<GrGLuint>(platformTimer);
|
| + GrGLuint64 nanoseconds;
|
| + fGLGetQueryObjectui64v(queryID, GL_QUERY_RESULT, &nanoseconds);
|
| + return std::chrono::nanoseconds(nanoseconds);
|
| +}
|
| +
|
| +void GLGpuTimer::deleteQuery(sk_gpu_test::PlatformTimerQuery platformTimer) {
|
| + const GrGLuint queryID = static_cast<GrGLuint>(platformTimer);
|
| + fGLDeleteQueries(1, &queryID);
|
| +}
|
| +
|
| +GR_STATIC_ASSERT(sizeof(GrGLuint) <= sizeof(sk_gpu_test::PlatformTimerQuery));
|
| +
|
| } // anonymous namespace
|
|
|
| namespace sk_gpu_test {
|
| @@ -92,6 +223,7 @@ void GLTestContext::init(const GrGLInterface* gl, FenceSync* fenceSync) {
|
| SkASSERT(!fGL.get());
|
| fGL.reset(gl);
|
| fFenceSync = fenceSync ? fenceSync : GLFenceSync::CreateIfSupported(this);
|
| + fGpuTimer = GLGpuTimer::CreateIfSupported(this);
|
| }
|
|
|
| void GLTestContext::teardown() {
|
|
|