Chromium Code Reviews| Index: tools/gpu/gl/GLTestContext.cpp |
| diff --git a/tools/gpu/gl/GLTestContext.cpp b/tools/gpu/gl/GLTestContext.cpp |
| index 68980922cdc4c986ef1c3fae325a2ec6dfd9a8bf..c42de1f915b28c2b4496ba348fa4a9ef2e594814 100644 |
| --- a/tools/gpu/gl/GLTestContext.cpp |
| +++ b/tools/gpu/gl/GLTestContext.cpp |
| @@ -6,9 +6,12 @@ |
| */ |
| #include "GLTestContext.h" |
| +#include "SkGpuTimer.h" |
| #include "gl/GrGLUtil.h" |
| +#include <string> |
| namespace sk_gpu_test { |
| + |
| class GLTestContext::GLFenceSync : public SkGpuFenceSync { |
| public: |
| static GLFenceSync* CreateIfSupported(const GLTestContext*); |
| @@ -20,9 +23,9 @@ public: |
| private: |
| GLFenceSync() {} |
| - static const GrGLenum GL_SYNC_GPU_COMMANDS_COMPLETE = 0x9117; |
| - static const GrGLenum GL_WAIT_FAILED = 0x911d; |
| - static const GrGLbitfield GL_SYNC_FLUSH_COMMANDS_BIT = 0x00000001; |
| + constexpr static GrGLenum GL_SYNC_GPU_COMMANDS_COMPLETE = 0x9117; |
|
bsalomon
2016/09/30 18:37:16
I believe we more commonly use "static constexpr"
csmartdalton
2016/10/03 16:52:24
Done.
|
| + constexpr static GrGLenum GL_WAIT_FAILED = 0x911d; |
| + constexpr static GrGLbitfield GL_SYNC_FLUSH_COMMANDS_BIT = 0x00000001; |
| typedef struct __GLsync *GLsync; |
| @@ -37,42 +40,6 @@ private: |
| typedef SkGpuFenceSync INHERITED; |
| }; |
| -GLTestContext::GLTestContext() : TestContext() {} |
| - |
| -GLTestContext::~GLTestContext() { |
| - SkASSERT(nullptr == fGL.get()); |
| -} |
| - |
| -void GLTestContext::init(const GrGLInterface* gl, SkGpuFenceSync* fenceSync) { |
| - SkASSERT(!fGL.get()); |
| - fGL.reset(gl); |
| - fFenceSync = fenceSync ? fenceSync : GLFenceSync::CreateIfSupported(this); |
| -} |
| - |
| -void GLTestContext::teardown() { |
| - fGL.reset(nullptr); |
| - INHERITED::teardown(); |
| -} |
| - |
| -void GLTestContext::testAbandon() { |
| - INHERITED::testAbandon(); |
| - if (fGL) { |
| - fGL->abandon(); |
| - } |
| -} |
| - |
| -void GLTestContext::submit() { |
| - if (fGL) { |
| - GR_GL_CALL(fGL.get(), Flush()); |
| - } |
| -} |
| - |
| -void GLTestContext::finish() { |
| - if (fGL) { |
| - GR_GL_CALL(fGL.get(), Finish()); |
| - } |
| -} |
| - |
| GLTestContext::GLFenceSync* GLTestContext::GLFenceSync::CreateIfSupported(const GLTestContext* ctx) { |
| SkAutoTDelete<GLFenceSync> ret(new GLFenceSync); |
| @@ -122,6 +89,188 @@ void GLTestContext::GLFenceSync::deleteFence(SkPlatformGpuFence fence) const { |
| fGLDeleteSync(glsync); |
| } |
| +//////////////////////////////////////////////////////////////////////////////////////////////////// |
| + |
| +class GLGpuTimer : public SkGpuTimer { |
| +public: |
| + static GLGpuTimer* CreateIfSupported(const GLTestContext*); |
| + |
| + QueryStatus checkQueryStatus(SkPlatformGpuTimerQuery) override; |
| + std::chrono::nanoseconds getTimeElapsed(SkPlatformGpuTimerQuery) override; |
| + void deleteQuery(SkPlatformGpuTimerQuery) override; |
| + |
| +private: |
| + GLGpuTimer(bool disjointSupport, const GLTestContext*, const char* ext = ""); |
| + |
| + template<typename Proc> void loadProc(Proc GLGpuTimer::* proc, const GLTestContext* ctx, |
| + const std::string& name, const std::string& ext = "") { |
| + const std::string& fullname = name + ext; |
| + this->*proc = reinterpret_cast<Proc>(ctx->onPlatformGetProcAddress(fullname.c_str())); |
| + } |
| + |
| + bool validate() const { |
| + return fGLGetIntegerv && fGLGenQueries && fGLDeleteQueries && fGLBeginQuery && fGLEndQuery |
| + && fGLQueryCounter && fGLGetQueryiv && fGLGetQueryObjectiv && fGLGetQueryObjectui64v; |
| + } |
| + |
| + SkPlatformGpuTimerQuery onQueueTimerStart() const override; |
| + void onQueueTimerStop(SkPlatformGpuTimerQuery) const override; |
| + |
| + constexpr static GrGLenum GL_QUERY_COUNTER_BITS = 0x8864; |
| + constexpr static GrGLenum GL_CURRENT_QUERY = 0x8865; |
| + constexpr static GrGLenum GL_QUERY_RESULT = 0x8866; |
| + constexpr static GrGLenum GL_QUERY_RESULT_AVAILABLE = 0x8867; |
| + constexpr static GrGLenum GL_TIME_ELAPSED = 0x88bf; |
| + constexpr static GrGLenum GL_TIMESTAMP = 0x8e28; |
| + constexpr static 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* GLQueryCounterProc) (GrGLuint, GrGLenum); |
| + typedef void (GR_GL_FUNCTION_TYPE* GLGetQueryivProc) (GrGLenum, GrGLenum, GrGLint *); |
| + typedef void (GR_GL_FUNCTION_TYPE* GLGetQueryObjectivProc) (GrGLuint, GrGLenum, GrGLint*); |
| + typedef void (GR_GL_FUNCTION_TYPE* GLGetQueryObjectui64vProc) (GrGLuint, GrGLenum, GrGLuint64*); |
| + |
| + GLGetIntegervProc fGLGetIntegerv; |
| + GLGenQueriesProc fGLGenQueries; |
| + GLDeleteQueriesProc fGLDeleteQueries; |
| + GLBeginQueryProc fGLBeginQuery; |
| + GLEndQueryProc fGLEndQuery; |
| + GLQueryCounterProc fGLQueryCounter; |
| + GLGetQueryivProc fGLGetQueryiv; |
| + GLGetQueryObjectivProc fGLGetQueryObjectiv; |
| + GLGetQueryObjectui64vProc fGLGetQueryObjectui64v; |
| +}; |
| + |
| +GLGpuTimer* GLGpuTimer::CreateIfSupported(const 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 GLTestContext* ctx, const char* ext) |
| + : SkGpuTimer(disjointSupport) { |
| + this->loadProc(&GLGpuTimer::fGLGetIntegerv, ctx, "glGetIntegerv"); |
| + this->loadProc(&GLGpuTimer::fGLGenQueries, ctx, "glGenQueries", ext); |
| + this->loadProc(&GLGpuTimer::fGLDeleteQueries, ctx, "glDeleteQueries", ext); |
| + this->loadProc(&GLGpuTimer::fGLBeginQuery, ctx, "glBeginQuery", ext); |
| + this->loadProc(&GLGpuTimer::fGLEndQuery, ctx, "glEndQuery", ext); |
| + this->loadProc(&GLGpuTimer::fGLQueryCounter, ctx, "glQueryCounter", ext); |
| + this->loadProc(&GLGpuTimer::fGLGetQueryiv, ctx, "glGetQueryiv", ext); |
| + this->loadProc(&GLGpuTimer::fGLGetQueryObjectiv, ctx, "glGetQueryObjectiv", ext); |
| + this->loadProc(&GLGpuTimer::fGLGetQueryObjectui64v, ctx, "glGetQueryObjectui64v", ext); |
| +} |
| + |
| +SkPlatformGpuTimerQuery GLGpuTimer::onQueueTimerStart() const { |
| + GrGLuint queryID; |
| + fGLGenQueries(1, &queryID); |
| + if (!queryID) { |
| + return SK_InvalidGpuTimerQuery; |
| + } |
| + if (this->disjointSupport()) { |
| + // Clear the disjoint flag. |
| + GrGLint disjoint; |
| + fGLGetIntegerv(GL_GPU_DISJOINT, &disjoint); |
| + } |
| + fGLBeginQuery(GL_TIME_ELAPSED, queryID); |
| + return static_cast<SkPlatformGpuTimerQuery>(queryID); |
| +} |
| + |
| +void GLGpuTimer::onQueueTimerStop(SkPlatformGpuTimerQuery platformTimer) const { |
| + if (SK_InvalidGpuTimerQuery == platformTimer) { |
| + return; |
| + } |
| + fGLEndQuery(GL_TIME_ELAPSED); |
| +} |
| + |
| +SkGpuTimer::QueryStatus GLGpuTimer::checkQueryStatus(SkPlatformGpuTimerQuery platformTimer) { |
| + const GrGLuint queryID = static_cast<GrGLuint>(platformTimer); |
| + if (!queryID) { |
| + return QueryStatus::kInvalid; |
| + } |
| + |
| + // Check if the timer has completed. We should really use the 32-bit version of glGetQueryObject |
| + // here, but it doesn't seem to work on Pixel C. |
| + GrGLuint64 available = 0; |
| + fGLGetQueryObjectui64v(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(SkPlatformGpuTimerQuery 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(SkPlatformGpuTimerQuery platformTimer) { |
| + const GrGLuint queryID = static_cast<GrGLuint>(platformTimer); |
| + fGLDeleteQueries(1, &queryID); |
| +} |
| + |
| +//////////////////////////////////////////////////////////////////////////////////////////////////// |
| + |
| +GLTestContext::GLTestContext() : TestContext() {} |
| + |
| +GLTestContext::~GLTestContext() { |
| + SkASSERT(nullptr == fGL.get()); |
| +} |
| + |
| +void GLTestContext::init(const GrGLInterface* gl, SkGpuFenceSync* fenceSync) { |
| + SkASSERT(!fGL.get()); |
| + fGL.reset(gl); |
| + fFenceSync = fenceSync ? fenceSync : GLFenceSync::CreateIfSupported(this); |
| + fGpuTimer = GLGpuTimer::CreateIfSupported(this); |
| +} |
| + |
| +void GLTestContext::teardown() { |
| + fGL.reset(nullptr); |
| + INHERITED::teardown(); |
| +} |
| + |
| +void GLTestContext::testAbandon() { |
| + INHERITED::testAbandon(); |
| + if (fGL) { |
| + fGL->abandon(); |
| + } |
| +} |
| + |
| +void GLTestContext::submit() { |
| + if (fGL) { |
| + GR_GL_CALL(fGL.get(), Flush()); |
| + } |
| +} |
| + |
| +void GLTestContext::finish() { |
| + if (fGL) { |
| + GR_GL_CALL(fGL.get(), Finish()); |
| + } |
| +} |
| + |
| GrGLint GLTestContext::createTextureRectangle(int width, int height, GrGLenum internalFormat, |
| GrGLenum externalFormat, GrGLenum externalType, |
| GrGLvoid* data) { |
| @@ -149,4 +298,5 @@ GrGLint GLTestContext::createTextureRectangle(int width, int height, GrGLenum in |
| externalFormat, externalType, data)); |
| return id; |
| } |
| + |
| } // namespace sk_gpu_test |