diff options
-rw-r--r-- | gyp/core.gypi | 1 | ||||
-rw-r--r-- | include/private/SkGpuFenceSync.h | 30 | ||||
-rw-r--r-- | tools/gpu/FenceSync.h | 34 | ||||
-rw-r--r-- | tools/gpu/TestContext.h | 12 | ||||
-rw-r--r-- | tools/gpu/gl/GLTestContext.cpp | 117 | ||||
-rw-r--r-- | tools/gpu/gl/GLTestContext.h | 22 | ||||
-rw-r--r-- | tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp | 23 | ||||
-rw-r--r-- | tools/gpu/vk/VkTestContext.cpp | 20 | ||||
-rw-r--r-- | tools/skpbench/skpbench.cpp | 18 |
9 files changed, 144 insertions, 133 deletions
diff --git a/gyp/core.gypi b/gyp/core.gypi index 50e3c3c09e..3409f28bb3 100644 --- a/gyp/core.gypi +++ b/gyp/core.gypi @@ -442,7 +442,6 @@ '<(skia_include_path)/private/SkFixed.h', '<(skia_include_path)/private/SkFloatBits.h', '<(skia_include_path)/private/SkFloatingPoint.h', - '<(skia_include_path)/private/SkGpuFenceSync.h', '<(skia_include_path)/private/SkMiniRecorder.h', '<(skia_include_path)/private/SkMutex.h', '<(skia_include_path)/private/SkOnce.h', diff --git a/include/private/SkGpuFenceSync.h b/include/private/SkGpuFenceSync.h deleted file mode 100644 index 5e5d3a6a4e..0000000000 --- a/include/private/SkGpuFenceSync.h +++ /dev/null @@ -1,30 +0,0 @@ - -/* - * Copyright 2015 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -#ifndef SkGpuFenceSync_DEFINED -#define SkGpuFenceSync_DEFINED - -#include "SkTypes.h" - -typedef void* SkPlatformGpuFence; -constexpr static SkPlatformGpuFence kInvalidPlatformGpuFence = nullptr; - -/* - * This class provides an interface to interact with fence syncs. A fence sync is an object that the - * client can insert into the GPU command stream, and then at any future time, wait until all - * commands that were issued before the fence have completed. - */ -class SkGpuFenceSync { -public: - virtual SkPlatformGpuFence SK_WARN_UNUSED_RESULT insertFence() const = 0; - virtual bool waitFence(SkPlatformGpuFence) const = 0; - virtual void deleteFence(SkPlatformGpuFence) const = 0; - - virtual ~SkGpuFenceSync() {} -}; - -#endif diff --git a/tools/gpu/FenceSync.h b/tools/gpu/FenceSync.h new file mode 100644 index 0000000000..c3f1182621 --- /dev/null +++ b/tools/gpu/FenceSync.h @@ -0,0 +1,34 @@ +/* + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef FenceSync_DEFINED +#define FenceSync_DEFINED + +#include "SkTypes.h" + +namespace sk_gpu_test { + +using PlatformFence = intptr_t; +static constexpr PlatformFence kInvalidPlatformFence = 0; + +/* + * This class provides an interface to interact with fence syncs. A fence sync is an object that the + * client can insert into the GPU command stream, and then at any future time, wait until all + * commands that were issued before the fence have completed. + */ +class FenceSync { +public: + virtual PlatformFence SK_WARN_UNUSED_RESULT insertFence() const = 0; + virtual bool waitFence(PlatformFence) const = 0; + virtual void deleteFence(PlatformFence) const = 0; + + virtual ~FenceSync() {} +}; + +} + +#endif diff --git a/tools/gpu/TestContext.h b/tools/gpu/TestContext.h index ffa8cae8f9..d01cb02af2 100644 --- a/tools/gpu/TestContext.h +++ b/tools/gpu/TestContext.h @@ -9,8 +9,8 @@ #ifndef TestContext_DEFINED #define TestContext_DEFINED +#include "FenceSync.h" #include "GrTypes.h" -#include "../private/SkGpuFenceSync.h" #include "../private/SkTemplates.h" namespace sk_gpu_test { @@ -25,6 +25,7 @@ public: virtual bool isValid() const = 0; bool fenceSyncSupport() const { return fFenceSync != nullptr; } + FenceSync* fenceSync() { SkASSERT(fFenceSync); return fFenceSync; } bool getMaxGpuFrameLag(int *maxFrameLag) const { if (!fFenceSync) { @@ -73,13 +74,8 @@ public: /** Wait until all GPU work is finished. */ virtual void finish() = 0; - /** - * returns the fencesync object owned by this GLTestContext - */ - SkGpuFenceSync *fenceSync() { return fFenceSync; } - protected: - SkGpuFenceSync* fFenceSync; + FenceSync* fFenceSync; TestContext(); @@ -94,7 +90,7 @@ private: kMaxFrameLag = 3 }; - SkPlatformGpuFence fFrameFences[kMaxFrameLag - 1]; + PlatformFence fFrameFences[kMaxFrameLag - 1]; int fCurrentFenceIdx; typedef SkNoncopyable INHERITED; diff --git a/tools/gpu/gl/GLTestContext.cpp b/tools/gpu/gl/GLTestContext.cpp index 68980922cd..1d53bbcd83 100644 --- a/tools/gpu/gl/GLTestContext.cpp +++ b/tools/gpu/gl/GLTestContext.cpp @@ -8,21 +8,24 @@ #include "GLTestContext.h" #include "gl/GrGLUtil.h" -namespace sk_gpu_test { -class GLTestContext::GLFenceSync : public SkGpuFenceSync { +namespace { + +class GLFenceSync : public sk_gpu_test::FenceSync { public: - static GLFenceSync* CreateIfSupported(const GLTestContext*); + static GLFenceSync* CreateIfSupported(const sk_gpu_test::GLTestContext*); - SkPlatformGpuFence SK_WARN_UNUSED_RESULT insertFence() const override; - bool waitFence(SkPlatformGpuFence fence) const override; - void deleteFence(SkPlatformGpuFence fence) const override; + sk_gpu_test::PlatformFence SK_WARN_UNUSED_RESULT insertFence() const override; + bool waitFence(sk_gpu_test::PlatformFence fence) const override; + void deleteFence(sk_gpu_test::PlatformFence fence) const override; private: - GLFenceSync() {} + GLFenceSync(const sk_gpu_test::GLTestContext*, const char* ext = ""); + + bool validate() { return fGLFenceSync && fGLClientWaitSync && fGLDeleteSync; } - 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; + static constexpr GrGLenum GL_SYNC_GPU_COMMANDS_COMPLETE = 0x9117; + static constexpr GrGLenum GL_WAIT_FAILED = 0x911d; + static constexpr GrGLbitfield GL_SYNC_FLUSH_COMMANDS_BIT = 0x00000001; typedef struct __GLsync *GLsync; @@ -34,16 +37,57 @@ private: GLClientWaitSyncProc fGLClientWaitSync; GLDeleteSyncProc fGLDeleteSync; - typedef SkGpuFenceSync INHERITED; + typedef FenceSync INHERITED; }; +GLFenceSync* GLFenceSync::CreateIfSupported(const sk_gpu_test::GLTestContext* ctx) { + SkAutoTDelete<GLFenceSync> ret; + if (kGL_GrGLStandard == ctx->gl()->fStandard) { + if (GrGLGetVersion(ctx->gl()) < GR_GL_VER(3,2) && !ctx->gl()->hasExtension("GL_ARB_sync")) { + return nullptr; + } + ret.reset(new GLFenceSync(ctx)); + } else { + if (!ctx->gl()->hasExtension("GL_APPLE_sync")) { + return nullptr; + } + ret.reset(new GLFenceSync(ctx, "APPLE")); + } + return ret->validate() ? ret.release() : nullptr; +} + +GLFenceSync::GLFenceSync(const sk_gpu_test::GLTestContext* ctx, const char* ext) { + ctx->getGLProcAddress(&fGLFenceSync, "glFenceSync"); + ctx->getGLProcAddress(&fGLClientWaitSync, "glClientWaitSync"); + ctx->getGLProcAddress(&fGLDeleteSync, "glDeleteSync"); +} + +sk_gpu_test::PlatformFence GLFenceSync::insertFence() const { + __GLsync* glsync = fGLFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + return reinterpret_cast<sk_gpu_test::PlatformFence>(glsync); +} + +bool GLFenceSync::waitFence(sk_gpu_test::PlatformFence fence) const { + GLsync glsync = reinterpret_cast<GLsync>(fence); + return GL_WAIT_FAILED != fGLClientWaitSync(glsync, GL_SYNC_FLUSH_COMMANDS_BIT, -1); +} + +void GLFenceSync::deleteFence(sk_gpu_test::PlatformFence fence) const { + GLsync glsync = reinterpret_cast<GLsync>(fence); + fGLDeleteSync(glsync); +} + +} // anonymous namespace + +namespace sk_gpu_test { + GLTestContext::GLTestContext() : TestContext() {} GLTestContext::~GLTestContext() { SkASSERT(nullptr == fGL.get()); } -void GLTestContext::init(const GrGLInterface* gl, SkGpuFenceSync* fenceSync) { +void GLTestContext::init(const GrGLInterface* gl, FenceSync* fenceSync) { SkASSERT(!fGL.get()); fGL.reset(gl); fFenceSync = fenceSync ? fenceSync : GLFenceSync::CreateIfSupported(this); @@ -73,55 +117,6 @@ void GLTestContext::finish() { } } -GLTestContext::GLFenceSync* GLTestContext::GLFenceSync::CreateIfSupported(const GLTestContext* ctx) { - SkAutoTDelete<GLFenceSync> ret(new GLFenceSync); - - if (kGL_GrGLStandard == ctx->gl()->fStandard) { - const GrGLubyte* versionStr; - GR_GL_CALL_RET(ctx->gl(), versionStr, GetString(GR_GL_VERSION)); - GrGLVersion version = GrGLGetVersionFromString(reinterpret_cast<const char*>(versionStr)); - if (version < GR_GL_VER(3,2) && !ctx->gl()->hasExtension("GL_ARB_sync")) { - return nullptr; - } - ret->fGLFenceSync = reinterpret_cast<GLFenceSyncProc>( - ctx->onPlatformGetProcAddress("glFenceSync")); - ret->fGLClientWaitSync = reinterpret_cast<GLClientWaitSyncProc>( - ctx->onPlatformGetProcAddress("glClientWaitSync")); - ret->fGLDeleteSync = reinterpret_cast<GLDeleteSyncProc>( - ctx->onPlatformGetProcAddress("glDeleteSync")); - } else { - if (!ctx->gl()->hasExtension("GL_APPLE_sync")) { - return nullptr; - } - ret->fGLFenceSync = reinterpret_cast<GLFenceSyncProc>( - ctx->onPlatformGetProcAddress("glFenceSyncAPPLE")); - ret->fGLClientWaitSync = reinterpret_cast<GLClientWaitSyncProc>( - ctx->onPlatformGetProcAddress("glClientWaitSyncAPPLE")); - ret->fGLDeleteSync = reinterpret_cast<GLDeleteSyncProc>( - ctx->onPlatformGetProcAddress("glDeleteSyncAPPLE")); - } - - if (!ret->fGLFenceSync || !ret->fGLClientWaitSync || !ret->fGLDeleteSync) { - return nullptr; - } - - return ret.release(); -} - -SkPlatformGpuFence GLTestContext::GLFenceSync::insertFence() const { - return fGLFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); -} - -bool GLTestContext::GLFenceSync::waitFence(SkPlatformGpuFence fence) const { - GLsync glsync = static_cast<GLsync>(fence); - return GL_WAIT_FAILED != fGLClientWaitSync(glsync, GL_SYNC_FLUSH_COMMANDS_BIT, -1); -} - -void GLTestContext::GLFenceSync::deleteFence(SkPlatformGpuFence fence) const { - GLsync glsync = static_cast<GLsync>(fence); - fGLDeleteSync(glsync); -} - GrGLint GLTestContext::createTextureRectangle(int width, int height, GrGLenum internalFormat, GrGLenum externalFormat, GrGLenum externalType, GrGLvoid* data) { diff --git a/tools/gpu/gl/GLTestContext.h b/tools/gpu/gl/GLTestContext.h index efe9d8f100..0cd9762f8b 100644 --- a/tools/gpu/gl/GLTestContext.h +++ b/tools/gpu/gl/GLTestContext.h @@ -59,27 +59,39 @@ public: */ virtual GLTestContext *createNew() const { return nullptr; } + template<typename Ret, typename... Args> + void getGLProcAddress(Ret(GR_GL_FUNCTION_TYPE** out)(Args...), + const char* name, const char* ext = nullptr) const { + using Proc = Ret(GR_GL_FUNCTION_TYPE*)(Args...); + if (!SkStrStartsWith(name, "gl")) { + SkFAIL("getGLProcAddress: proc name must have 'gl' prefix"); + *out = nullptr; + } else if (ext) { + SkString fullname(name); + fullname.append(ext); + *out = reinterpret_cast<Proc>(this->onPlatformGetProcAddress(fullname.c_str())); + } else { + *out = reinterpret_cast<Proc>(this->onPlatformGetProcAddress(name)); + } + } + protected: GLTestContext(); /* * Methods that sublcasses must call from their constructors and destructors. */ - void init(const GrGLInterface *, SkGpuFenceSync * = NULL); + void init(const GrGLInterface *, FenceSync* = nullptr); void teardown() override; virtual GrGLFuncPtr onPlatformGetProcAddress(const char *) const = 0; private: - class GLFenceSync; // SkGpuFenceSync implementation that uses the OpenGL functionality. - /** Subclass provides the gl interface object if construction was * successful. */ SkAutoTUnref<const GrGLInterface> fGL; - friend class GLFenceSync; // For onPlatformGetProcAddress. - typedef TestContext INHERITED; }; diff --git a/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp b/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp index edbc63200b..8fdd3fea86 100644 --- a/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp +++ b/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp @@ -20,20 +20,20 @@ namespace { // TODO: Share this class with ANGLE if/when it gets support for EGL_KHR_fence_sync. -class EGLFenceSync : public SkGpuFenceSync { +class EGLFenceSync : public sk_gpu_test::FenceSync { public: static EGLFenceSync* CreateIfSupported(EGLDisplay); - SkPlatformGpuFence SK_WARN_UNUSED_RESULT insertFence() const override; - bool waitFence(SkPlatformGpuFence fence) const override; - void deleteFence(SkPlatformGpuFence fence) const override; + sk_gpu_test::PlatformFence SK_WARN_UNUSED_RESULT insertFence() const override; + bool waitFence(sk_gpu_test::PlatformFence fence) const override; + void deleteFence(sk_gpu_test::PlatformFence fence) const override; private: EGLFenceSync(EGLDisplay display) : fDisplay(display) {} EGLDisplay fDisplay; - typedef SkGpuFenceSync INHERITED; + typedef sk_gpu_test::FenceSync INHERITED; }; class EGLGLTestContext : public sk_gpu_test::GLTestContext { @@ -301,12 +301,13 @@ EGLFenceSync* EGLFenceSync::CreateIfSupported(EGLDisplay display) { return new EGLFenceSync(display); } -SkPlatformGpuFence EGLFenceSync::insertFence() const { - return eglCreateSyncKHR(fDisplay, EGL_SYNC_FENCE_KHR, nullptr); +sk_gpu_test::PlatformFence EGLFenceSync::insertFence() const { + EGLSyncKHR eglsync = eglCreateSyncKHR(fDisplay, EGL_SYNC_FENCE_KHR, nullptr); + return reinterpret_cast<sk_gpu_test::PlatformFence>(eglsync); } -bool EGLFenceSync::waitFence(SkPlatformGpuFence platformFence) const { - EGLSyncKHR eglsync = static_cast<EGLSyncKHR>(platformFence); +bool EGLFenceSync::waitFence(sk_gpu_test::PlatformFence platformFence) const { + EGLSyncKHR eglsync = reinterpret_cast<EGLSyncKHR>(platformFence); return EGL_CONDITION_SATISFIED_KHR == eglClientWaitSyncKHR(fDisplay, eglsync, @@ -314,8 +315,8 @@ bool EGLFenceSync::waitFence(SkPlatformGpuFence platformFence) const { EGL_FOREVER_KHR); } -void EGLFenceSync::deleteFence(SkPlatformGpuFence platformFence) const { - EGLSyncKHR eglsync = static_cast<EGLSyncKHR>(platformFence); +void EGLFenceSync::deleteFence(sk_gpu_test::PlatformFence platformFence) const { + EGLSyncKHR eglsync = reinterpret_cast<EGLSyncKHR>(platformFence); eglDestroySyncKHR(fDisplay, eglsync); } diff --git a/tools/gpu/vk/VkTestContext.cpp b/tools/gpu/vk/VkTestContext.cpp index 02bda2fa31..c1a2f8ab56 100644 --- a/tools/gpu/vk/VkTestContext.cpp +++ b/tools/gpu/vk/VkTestContext.cpp @@ -15,11 +15,11 @@ namespace { /** - * Implements SkGpuFenceSync for Vulkan. It creates a single command buffer with - * USAGE_SIMULTANEOUS with no content . On every insertFence request it submits - * the command buffer with a new fence. + * Implements sk_gpu_test::FenceSync for Vulkan. It creates a single command + * buffer with USAGE_SIMULTANEOUS with no content . On every insertFence request + * it submits the command buffer with a new fence. */ -class VkFenceSync : public SkGpuFenceSync { +class VkFenceSync : public sk_gpu_test::FenceSync { public: VkFenceSync(sk_sp<const GrVkInterface> vk, VkDevice device, VkQueue queue, uint32_t queueFamilyIndex) @@ -58,7 +58,7 @@ public: GR_VK_CALL(fVk, DestroyCommandPool(fDevice, fCommandPool, nullptr)); } - SkPlatformGpuFence SK_WARN_UNUSED_RESULT insertFence() const override { + sk_gpu_test::PlatformFence SK_WARN_UNUSED_RESULT insertFence() const override { VkFence fence; VkFenceCreateInfo info; info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; @@ -77,17 +77,17 @@ public: submitInfo.pSignalSemaphores = nullptr; GR_VK_CALL_ERRCHECK(fVk, QueueSubmit(fQueue, 1, &submitInfo, fence)); SkDEBUGCODE(++fUnfinishedSyncs;) - return reinterpret_cast<SkPlatformGpuFence>(fence); + return reinterpret_cast<sk_gpu_test::PlatformFence>(fence); } - bool waitFence(SkPlatformGpuFence opaqueFence) const override { + bool waitFence(sk_gpu_test::PlatformFence opaqueFence) const override { VkFence fence = reinterpret_cast<VkFence>(opaqueFence); static constexpr uint64_t kForever = ~((uint64_t)0); auto result = GR_VK_CALL(fVk, WaitForFences(fDevice, 1, &fence, true, kForever)); return result != VK_TIMEOUT; } - void deleteFence(SkPlatformGpuFence opaqueFence) const override { + void deleteFence(sk_gpu_test::PlatformFence opaqueFence) const override { VkFence fence = reinterpret_cast<VkFence>(opaqueFence); GR_VK_CALL(fVk, DestroyFence(fDevice, fence, nullptr)); SkDEBUGCODE(--fUnfinishedSyncs;) @@ -100,7 +100,7 @@ private: VkCommandPool fCommandPool; VkCommandBuffer fCommandBuffer; SkDEBUGCODE(mutable int fUnfinishedSyncs;) - typedef SkGpuFenceSync INHERITED; + typedef sk_gpu_test::FenceSync INHERITED; }; // TODO: Implement swap buffers and finish @@ -141,7 +141,7 @@ private: typedef sk_gpu_test::VkTestContext INHERITED; }; -} +} // anonymous namespace namespace sk_gpu_test { VkTestContext* CreatePlatformVkTestContext() { return VkTestContextImpl::Create(); } diff --git a/tools/skpbench/skpbench.cpp b/tools/skpbench/skpbench.cpp index 734a1b79b2..adb6af0b14 100644 --- a/tools/skpbench/skpbench.cpp +++ b/tools/skpbench/skpbench.cpp @@ -33,6 +33,10 @@ * Currently, only GPU configs are supported. */ +using sk_gpu_test::PlatformFence; +using sk_gpu_test::kInvalidPlatformFence; +using sk_gpu_test::FenceSync; + DEFINE_int32(duration, 5000, "number of milliseconds to run the benchmark"); DEFINE_int32(sampleMs, 50, "minimum duration of a sample"); DEFINE_bool(fps, false, "use fps instead of ms"); @@ -62,7 +66,7 @@ struct Sample { class GpuSync { public: - GpuSync(const SkGpuFenceSync* fenceSync); + GpuSync(const FenceSync* fenceSync); ~GpuSync(); void syncToPreviousFrame(); @@ -70,8 +74,8 @@ public: private: void updateFence(); - const SkGpuFenceSync* const fFenceSync; - SkPlatformGpuFence fFence; + const FenceSync* const fFenceSync; + PlatformFence fFence; }; enum class ExitErr { @@ -88,7 +92,7 @@ static bool mkdir_p(const SkString& name); static SkString join(const SkCommandLineFlags::StringArray&); static void exitf(ExitErr, const char* format, ...); -static void run_benchmark(const SkGpuFenceSync* fenceSync, SkCanvas* canvas, const SkPicture* skp, +static void run_benchmark(const FenceSync* fenceSync, SkCanvas* canvas, const SkPicture* skp, std::vector<Sample>* samples) { using clock = Sample::clock; const clock::duration sampleDuration = std::chrono::milliseconds(FLAGS_sampleMs); @@ -296,7 +300,7 @@ static void exitf(ExitErr err, const char* format, ...) { exit((int)err); } -GpuSync::GpuSync(const SkGpuFenceSync* fenceSync) +GpuSync::GpuSync(const FenceSync* fenceSync) : fFenceSync(fenceSync) { this->updateFence(); } @@ -306,7 +310,7 @@ GpuSync::~GpuSync() { } void GpuSync::syncToPreviousFrame() { - if (kInvalidPlatformGpuFence == fFence) { + if (kInvalidPlatformFence == fFence) { exitf(ExitErr::kSoftware, "attempted to sync with invalid fence"); } if (!fFenceSync->waitFence(fFence)) { @@ -318,7 +322,7 @@ void GpuSync::syncToPreviousFrame() { void GpuSync::updateFence() { fFence = fFenceSync->insertFence(); - if (kInvalidPlatformGpuFence == fFence) { + if (kInvalidPlatformFence == fFence) { exitf(ExitErr::kUnavailable, "failed to insert fence"); } } |