diff options
-rw-r--r-- | include/private/SkGpuFenceSync.h | 2 | ||||
-rw-r--r-- | tools/gpu/TestContext.cpp | 2 | ||||
-rw-r--r-- | tools/gpu/gl/GLTestContext.cpp | 6 | ||||
-rw-r--r-- | tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp | 6 | ||||
-rw-r--r-- | tools/gpu/vk/VkTestContext.cpp | 121 | ||||
-rw-r--r-- | tools/kilobench/kilobench.cpp | 2 |
6 files changed, 123 insertions, 16 deletions
diff --git a/include/private/SkGpuFenceSync.h b/include/private/SkGpuFenceSync.h index 72fd241078..09f5e6e171 100644 --- a/include/private/SkGpuFenceSync.h +++ b/include/private/SkGpuFenceSync.h @@ -20,7 +20,7 @@ typedef void* SkPlatformGpuFence; class SkGpuFenceSync { public: virtual SkPlatformGpuFence SK_WARN_UNUSED_RESULT insertFence() const = 0; - virtual bool waitFence(SkPlatformGpuFence, bool flush) const = 0; + virtual bool waitFence(SkPlatformGpuFence) const = 0; virtual void deleteFence(SkPlatformGpuFence) const = 0; virtual ~SkGpuFenceSync() {} diff --git a/tools/gpu/TestContext.cpp b/tools/gpu/TestContext.cpp index c6900fe41d..8a78b903b1 100644 --- a/tools/gpu/TestContext.cpp +++ b/tools/gpu/TestContext.cpp @@ -36,7 +36,7 @@ void TestContext::waitOnSyncOrSwap() { this->submit(); if (fFrameFences[fCurrentFenceIdx]) { - if (!fFenceSync->waitFence(fFrameFences[fCurrentFenceIdx], true)) { + if (!fFenceSync->waitFence(fFrameFences[fCurrentFenceIdx])) { SkDebugf("WARNING: Wait failed for fence sync. Timings might not be accurate.\n"); } fFenceSync->deleteFence(fFrameFences[fCurrentFenceIdx]); diff --git a/tools/gpu/gl/GLTestContext.cpp b/tools/gpu/gl/GLTestContext.cpp index 87cf724139..68980922cd 100644 --- a/tools/gpu/gl/GLTestContext.cpp +++ b/tools/gpu/gl/GLTestContext.cpp @@ -14,7 +14,7 @@ public: static GLFenceSync* CreateIfSupported(const GLTestContext*); SkPlatformGpuFence SK_WARN_UNUSED_RESULT insertFence() const override; - bool waitFence(SkPlatformGpuFence fence, bool flush) const override; + bool waitFence(SkPlatformGpuFence fence) const override; void deleteFence(SkPlatformGpuFence fence) const override; private: @@ -112,9 +112,9 @@ SkPlatformGpuFence GLTestContext::GLFenceSync::insertFence() const { return fGLFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); } -bool GLTestContext::GLFenceSync::waitFence(SkPlatformGpuFence fence, bool flush) const { +bool GLTestContext::GLFenceSync::waitFence(SkPlatformGpuFence fence) const { GLsync glsync = static_cast<GLsync>(fence); - return GL_WAIT_FAILED != fGLClientWaitSync(glsync, flush ? GL_SYNC_FLUSH_COMMANDS_BIT : 0, -1); + return GL_WAIT_FAILED != fGLClientWaitSync(glsync, GL_SYNC_FLUSH_COMMANDS_BIT, -1); } void GLTestContext::GLFenceSync::deleteFence(SkPlatformGpuFence fence) const { diff --git a/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp b/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp index ae61b337d9..edbc63200b 100644 --- a/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp +++ b/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp @@ -25,7 +25,7 @@ public: static EGLFenceSync* CreateIfSupported(EGLDisplay); SkPlatformGpuFence SK_WARN_UNUSED_RESULT insertFence() const override; - bool waitFence(SkPlatformGpuFence fence, bool flush) const override; + bool waitFence(SkPlatformGpuFence fence) const override; void deleteFence(SkPlatformGpuFence fence) const override; private: @@ -305,12 +305,12 @@ SkPlatformGpuFence EGLFenceSync::insertFence() const { return eglCreateSyncKHR(fDisplay, EGL_SYNC_FENCE_KHR, nullptr); } -bool EGLFenceSync::waitFence(SkPlatformGpuFence platformFence, bool flush) const { +bool EGLFenceSync::waitFence(SkPlatformGpuFence platformFence) const { EGLSyncKHR eglsync = static_cast<EGLSyncKHR>(platformFence); return EGL_CONDITION_SATISFIED_KHR == eglClientWaitSyncKHR(fDisplay, eglsync, - flush ? EGL_SYNC_FLUSH_COMMANDS_BIT_KHR : 0, + EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR); } diff --git a/tools/gpu/vk/VkTestContext.cpp b/tools/gpu/vk/VkTestContext.cpp index f6849e4484..02bda2fa31 100644 --- a/tools/gpu/vk/VkTestContext.cpp +++ b/tools/gpu/vk/VkTestContext.cpp @@ -9,24 +9,133 @@ #ifdef SK_VULKAN +#include "vk/GrVkInterface.h" +#include "vk/GrVkUtil.h" +#include <vulkan/vulkan.h> + namespace { -// TODO: Implement fence syncs, swap buffers, submit, and flush +/** + * 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. + */ +class VkFenceSync : public SkGpuFenceSync { +public: + VkFenceSync(sk_sp<const GrVkInterface> vk, VkDevice device, VkQueue queue, + uint32_t queueFamilyIndex) + : fVk(std::move(vk)) + , fDevice(device) + , fQueue(queue) { + SkDEBUGCODE(fUnfinishedSyncs = 0;) + VkCommandPoolCreateInfo createInfo; + createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + createInfo.pNext = nullptr; + createInfo.flags = 0; + createInfo.queueFamilyIndex = queueFamilyIndex; + GR_VK_CALL_ERRCHECK(fVk, CreateCommandPool(fDevice, &createInfo, nullptr, &fCommandPool)); + + VkCommandBufferAllocateInfo allocateInfo; + allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + allocateInfo.pNext = nullptr; + allocateInfo.commandBufferCount = 1; + allocateInfo.commandPool = fCommandPool; + allocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + GR_VK_CALL_ERRCHECK(fVk, AllocateCommandBuffers(fDevice, &allocateInfo, &fCommandBuffer)); + + VkCommandBufferBeginInfo beginInfo; + beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + beginInfo.pNext = nullptr; + beginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT; + beginInfo.pInheritanceInfo = nullptr; + GR_VK_CALL_ERRCHECK(fVk, BeginCommandBuffer(fCommandBuffer, &beginInfo)); + GR_VK_CALL_ERRCHECK(fVk, EndCommandBuffer(fCommandBuffer)); + } + + ~VkFenceSync() override { + SkASSERT(!fUnfinishedSyncs); + // If the above assertion is true then the command buffer should not be in flight. + GR_VK_CALL(fVk, FreeCommandBuffers(fDevice, fCommandPool, 1, &fCommandBuffer)); + GR_VK_CALL(fVk, DestroyCommandPool(fDevice, fCommandPool, nullptr)); + } + + SkPlatformGpuFence SK_WARN_UNUSED_RESULT insertFence() const override { + VkFence fence; + VkFenceCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + GR_VK_CALL_ERRCHECK(fVk, CreateFence(fDevice, &info, nullptr, &fence)); + VkSubmitInfo submitInfo; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.pNext = nullptr; + submitInfo.waitSemaphoreCount = 0; + submitInfo.pWaitSemaphores = nullptr; + submitInfo.pWaitDstStageMask = nullptr; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &fCommandBuffer; + submitInfo.signalSemaphoreCount = 0; + submitInfo.pSignalSemaphores = nullptr; + GR_VK_CALL_ERRCHECK(fVk, QueueSubmit(fQueue, 1, &submitInfo, fence)); + SkDEBUGCODE(++fUnfinishedSyncs;) + return reinterpret_cast<SkPlatformGpuFence>(fence); + } + + bool waitFence(SkPlatformGpuFence 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 { + VkFence fence = reinterpret_cast<VkFence>(opaqueFence); + GR_VK_CALL(fVk, DestroyFence(fDevice, fence, nullptr)); + SkDEBUGCODE(--fUnfinishedSyncs;) + } + +private: + sk_sp<const GrVkInterface> fVk; + VkDevice fDevice; + VkQueue fQueue; + VkCommandPool fCommandPool; + VkCommandBuffer fCommandBuffer; + SkDEBUGCODE(mutable int fUnfinishedSyncs;) + typedef SkGpuFenceSync INHERITED; +}; + +// TODO: Implement swap buffers and finish class VkTestContextImpl : public sk_gpu_test::VkTestContext { public: - VkTestContextImpl() - : VkTestContext(sk_sp<const GrVkBackendContext>(GrVkBackendContext::Create())) {} + static VkTestContext* Create() { + sk_sp<const GrVkBackendContext> backendContext(GrVkBackendContext::Create()); + if (!backendContext) { + return nullptr; + } + return new VkTestContextImpl(std::move(backendContext)); + } ~VkTestContextImpl() override { this->teardown(); } void testAbandon() override {} + // There is really nothing to here since we don't own any unqueued command buffers here. void submit() override {} + void finish() override {} protected: - void teardown() override { fVk.reset(nullptr); } + void teardown() override { + INHERITED::teardown(); + fVk.reset(nullptr); + } private: + VkTestContextImpl(sk_sp<const GrVkBackendContext> backendContext) + : VkTestContext(std::move(backendContext)) { + fFenceSync = new VkFenceSync(sk_ref_sp(fVk->fInterface.get()), fVk->fDevice, fVk->fQueue, + fVk->fGraphicsQueueIndex); + } + void onPlatformMakeCurrent() const override {} void onPlatformSwapBuffers() const override {} @@ -35,9 +144,7 @@ private: } namespace sk_gpu_test { -VkTestContext* CreatePlatformVkTestContext() { - return new VkTestContextImpl; -} +VkTestContext* CreatePlatformVkTestContext() { return VkTestContextImpl::Create(); } } // namespace sk_gpu_test #endif diff --git a/tools/kilobench/kilobench.cpp b/tools/kilobench/kilobench.cpp index b14770f458..02c9fc60bc 100644 --- a/tools/kilobench/kilobench.cpp +++ b/tools/kilobench/kilobench.cpp @@ -302,7 +302,7 @@ struct TimingThread { void waitFence(SkPlatformGpuFence sync) { SkDEBUGCODE(double start = now_ms()); - fFenceSync->waitFence(sync, false); + fFenceSync->waitFence(sync); SkASSERT(sanity(start)); } |