aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Greg Daniel <egdaniel@google.com>2017-07-20 15:47:30 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-07-20 20:26:28 +0000
commitdba7e7ccfbab1c99b8a3f81156cecdb630d7d03a (patch)
tree1254893d643a529bcc916393c77991bbf705c5c3
parentc7d295ecf712dece58ae6654721b3708fd8a40d6 (diff)
Add test for flushing empty surface with semaphores
Bug: skia: Change-Id: I8d7dcb29c5b4c460aa5137842caf6563448ba5d3 Reviewed-on: https://skia-review.googlesource.com/25181 Commit-Queue: Greg Daniel <egdaniel@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com>
-rw-r--r--include/gpu/gl/GrGLFunctions.h1
-rw-r--r--include/gpu/gl/GrGLInterface.h1
-rw-r--r--src/gpu/gl/GrGLAssembleInterface.cpp3
-rw-r--r--src/gpu/gl/GrGLInterface.cpp4
-rw-r--r--src/gpu/gl/GrGLTestInterface.cpp1
-rw-r--r--src/gpu/gl/GrGLTestInterface.h1
-rw-r--r--tests/SurfaceSemaphoreTest.cpp111
7 files changed, 122 insertions, 0 deletions
diff --git a/include/gpu/gl/GrGLFunctions.h b/include/gpu/gl/GrGLFunctions.h
index 5166a4b099..c1b3d0dd68 100644
--- a/include/gpu/gl/GrGLFunctions.h
+++ b/include/gpu/gl/GrGLFunctions.h
@@ -353,6 +353,7 @@ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLTextureBufferProc)(GrGLuint texture,
/* ARB_sync */
typedef GrGLsync (GR_GL_FUNCTION_TYPE* GrGLFenceSyncProc)(GrGLenum condition, GrGLbitfield flags);
+typedef GrGLboolean (GR_GL_FUNCTION_TYPE* GrGLIsSyncProc)(GrGLsync sync);
typedef GrGLenum (GR_GL_FUNCTION_TYPE* GrGLClientWaitSyncProc)(GrGLsync sync, GrGLbitfield flags, GrGLuint64 timeout);
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLWaitSyncProc)(GrGLsync sync, GrGLbitfield flags, GrGLuint64 timeout);
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDeleteSyncProc)(GrGLsync sync);
diff --git a/include/gpu/gl/GrGLInterface.h b/include/gpu/gl/GrGLInterface.h
index 10880471ce..56e655d887 100644
--- a/include/gpu/gl/GrGLInterface.h
+++ b/include/gpu/gl/GrGLInterface.h
@@ -456,6 +456,7 @@ public:
/* ARB_sync */
GrGLFunction<GrGLFenceSyncProc> fFenceSync;
+ GrGLFunction<GrGLIsSyncProc> fIsSync;
GrGLFunction<GrGLClientWaitSyncProc> fClientWaitSync;
GrGLFunction<GrGLWaitSyncProc> fWaitSync;
GrGLFunction<GrGLDeleteSyncProc> fDeleteSync;
diff --git a/src/gpu/gl/GrGLAssembleInterface.cpp b/src/gpu/gl/GrGLAssembleInterface.cpp
index 64bed32136..6b0234abb7 100644
--- a/src/gpu/gl/GrGLAssembleInterface.cpp
+++ b/src/gpu/gl/GrGLAssembleInterface.cpp
@@ -516,6 +516,7 @@ const GrGLInterface* GrGLAssembleGLInterface(void* ctx, GrGLGetProc get) {
if (glVer >= GR_GL_VER(3, 2) || extensions.has("GL_ARB_sync")) {
GET_PROC(FenceSync);
+ GET_PROC(IsSync);
GET_PROC(ClientWaitSync);
GET_PROC(WaitSync);
GET_PROC(DeleteSync);
@@ -940,11 +941,13 @@ const GrGLInterface* GrGLAssembleGLESInterface(void* ctx, GrGLGetProc get) {
if (version >= GR_GL_VER(3, 0)) {
GET_PROC(FenceSync);
+ GET_PROC(IsSync);
GET_PROC(ClientWaitSync);
GET_PROC(WaitSync);
GET_PROC(DeleteSync);
} else if (extensions.has("GL_APPLE_sync")) {
GET_PROC_SUFFIX(FenceSync, APPLE);
+ GET_PROC_SUFFIX(IsSync, APPLE);
GET_PROC_SUFFIX(ClientWaitSync, APPLE);
GET_PROC_SUFFIX(WaitSync, APPLE);
GET_PROC_SUFFIX(DeleteSync, APPLE);
diff --git a/src/gpu/gl/GrGLInterface.cpp b/src/gpu/gl/GrGLInterface.cpp
index 09d7a4fad3..dcad07e1f2 100644
--- a/src/gpu/gl/GrGLInterface.cpp
+++ b/src/gpu/gl/GrGLInterface.cpp
@@ -757,6 +757,8 @@ bool GrGLInterface::validate() const {
if (kGL_GrGLStandard == fStandard) {
if (glVer >= GR_GL_VER(3, 2) || fExtensions.has("GL_ARB_sync")) {
if (nullptr == fFunctions.fFenceSync ||
+ // Is sync needs to be added to chrome before uncommenting
+ // nullptr == fFunctions.fIsSync ||
nullptr == fFunctions.fClientWaitSync ||
nullptr == fFunctions.fWaitSync ||
nullptr == fFunctions.fDeleteSync) {
@@ -766,6 +768,8 @@ bool GrGLInterface::validate() const {
} else if (kGLES_GrGLStandard == fStandard) {
if (glVer >= GR_GL_VER(3, 0) || fExtensions.has("GL_APPLE_sync")) {
if (nullptr == fFunctions.fFenceSync ||
+ // Is sync needs to be added to chrome before uncommenting
+ // nullptr == fFunctions.fIsSync ||
nullptr == fFunctions.fClientWaitSync ||
nullptr == fFunctions.fWaitSync ||
nullptr == fFunctions.fDeleteSync) {
diff --git a/src/gpu/gl/GrGLTestInterface.cpp b/src/gpu/gl/GrGLTestInterface.cpp
index ef86ea71b9..45482e0066 100644
--- a/src/gpu/gl/GrGLTestInterface.cpp
+++ b/src/gpu/gl/GrGLTestInterface.cpp
@@ -314,6 +314,7 @@ GrGLTestInterface::GrGLTestInterface() {
fFunctions.fFlushMappedNamedBufferRange = bind_to_member(this, &GrGLTestInterface::flushMappedNamedBufferRange);
fFunctions.fTextureBuffer = bind_to_member(this, &GrGLTestInterface::textureBuffer);
fFunctions.fFenceSync = bind_to_member(this, &GrGLTestInterface::fenceSync);
+ fFunctions.fIsSync = bind_to_member(this, &GrGLTestInterface::isSync);
fFunctions.fClientWaitSync = bind_to_member(this, &GrGLTestInterface::clientWaitSync);
fFunctions.fWaitSync = bind_to_member(this, &GrGLTestInterface::waitSync);
fFunctions.fDeleteSync = bind_to_member(this, &GrGLTestInterface::deleteSync);
diff --git a/src/gpu/gl/GrGLTestInterface.h b/src/gpu/gl/GrGLTestInterface.h
index 69427f8d5a..1ebf90b7cf 100644
--- a/src/gpu/gl/GrGLTestInterface.h
+++ b/src/gpu/gl/GrGLTestInterface.h
@@ -319,6 +319,7 @@ public:
virtual GrGLvoid flushMappedNamedBufferRange(GrGLuint buffer, GrGLintptr offset, GrGLsizeiptr length) {}
virtual GrGLvoid textureBuffer(GrGLuint texture, GrGLenum target, GrGLenum internalformat, GrGLuint buffer) {}
virtual GrGLsync fenceSync(GrGLenum condition, GrGLbitfield flags) { return nullptr; }
+ virtual GrGLboolean isSync(GrGLsync) { return false; }
virtual GrGLenum clientWaitSync(GrGLsync sync, GrGLbitfield flags, GrGLuint64 timeout) { return GR_GL_WAIT_FAILED; }
virtual GrGLvoid waitSync(GrGLsync sync, GrGLbitfield flags, GrGLuint64 timeout) {}
virtual GrGLvoid deleteSync(GrGLsync sync) {}
diff --git a/tests/SurfaceSemaphoreTest.cpp b/tests/SurfaceSemaphoreTest.cpp
index 72e8e05401..7b22e1cf33 100644
--- a/tests/SurfaceSemaphoreTest.cpp
+++ b/tests/SurfaceSemaphoreTest.cpp
@@ -17,8 +17,18 @@
#include "SkCanvas.h"
#include "SkSurface.h"
+#include "gl/GrGLGpu.h"
+#include "gl/GrGLUtil.h"
+
#ifdef SK_VULKAN
+#include "vk/GrVkGpu.h"
#include "vk/GrVkTypes.h"
+#include "vk/GrVkUtil.h"
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+// windows wants to define this as CreateSemaphoreA or CreateSemaphoreW
+ #undef CreateSemaphore
+ #endif
#endif
static const int MAIN_W = 8, MAIN_H = 16;
@@ -172,4 +182,105 @@ DEF_GPUTEST(SurfaceSemaphores, reporter, factory) {
}
}
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(EmptySurfaceSemaphoreTest, reporter, ctxInfo) {
+ GrContext* ctx = ctxInfo.grContext();
+ if (!ctx->caps()->fenceSyncSupport()) {
+ return;
+ }
+
+ const SkImageInfo ii = SkImageInfo::Make(MAIN_W, MAIN_H, kRGBA_8888_SkColorType,
+ kPremul_SkAlphaType);
+
+ sk_sp<SkSurface> mainSurface(SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo,
+ ii, 0, kTopLeft_GrSurfaceOrigin,
+ nullptr));
+
+ // Flush surface once without semaphores to make sure there is no peneding IO for it.
+ mainSurface->flush();
+
+ GrBackendSemaphore semaphore;
+ REPORTER_ASSERT(reporter, mainSurface->flushAndSignalSemaphores(1, &semaphore));
+
+ if (kOpenGL_GrBackend == ctxInfo.backend()) {
+ GrGLGpu* gpu = static_cast<GrGLGpu*>(ctx->getGpu());
+ const GrGLInterface* interface = gpu->glInterface();
+ GrGLsync sync = semaphore.glSync();
+ REPORTER_ASSERT(reporter, sync);
+ bool result;
+ GR_GL_CALL_RET(interface, result, IsSync(sync));
+ REPORTER_ASSERT(reporter, result);
+ }
+
+#ifdef SK_VULKAN
+ if (kVulkan_GrBackend == ctxInfo.backend()) {
+ GrVkGpu* gpu = static_cast<GrVkGpu*>(ctx->getGpu());
+ const GrVkInterface* interface = gpu->vkInterface();
+ VkDevice device = gpu->device();
+ VkQueue queue = gpu->queue();
+ VkCommandPool cmdPool = gpu->cmdPool();
+ VkCommandBuffer cmdBuffer;
+
+ // Create Command Buffer
+ const VkCommandBufferAllocateInfo cmdInfo = {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType
+ nullptr, // pNext
+ cmdPool, // commandPool
+ VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level
+ 1 // bufferCount
+ };
+
+ VkResult err = GR_VK_CALL(interface, AllocateCommandBuffers(device, &cmdInfo, &cmdBuffer));
+ if (err) {
+ return;
+ }
+
+ VkCommandBufferBeginInfo cmdBufferBeginInfo;
+ memset(&cmdBufferBeginInfo, 0, sizeof(VkCommandBufferBeginInfo));
+ cmdBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ cmdBufferBeginInfo.pNext = nullptr;
+ cmdBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+ cmdBufferBeginInfo.pInheritanceInfo = nullptr;
+
+ GR_VK_CALL_ERRCHECK(interface, BeginCommandBuffer(cmdBuffer, &cmdBufferBeginInfo));
+ GR_VK_CALL_ERRCHECK(interface, EndCommandBuffer(cmdBuffer));
+
+ VkFenceCreateInfo fenceInfo;
+ VkFence fence;
+
+ memset(&fenceInfo, 0, sizeof(VkFenceCreateInfo));
+ fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+ err = GR_VK_CALL(interface, CreateFence(device, &fenceInfo, nullptr, &fence));
+ SkASSERT(!err);
+
+ VkPipelineStageFlags waitStages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
+ VkSubmitInfo submitInfo;
+ memset(&submitInfo, 0, sizeof(VkSubmitInfo));
+ submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submitInfo.pNext = nullptr;
+ submitInfo.waitSemaphoreCount = 1;
+ VkSemaphore vkSem = semaphore.vkSemaphore();
+ submitInfo.pWaitSemaphores = &vkSem;
+ submitInfo.pWaitDstStageMask = &waitStages;
+ submitInfo.commandBufferCount = 1;
+ submitInfo.pCommandBuffers = &cmdBuffer;
+ submitInfo.signalSemaphoreCount = 0;
+ submitInfo.pSignalSemaphores = nullptr;
+ GR_VK_CALL_ERRCHECK(interface, QueueSubmit(queue, 1, &submitInfo, fence));
+
+ err = GR_VK_CALL(interface, WaitForFences(device, 1, &fence, true, 3000000000));
+
+ REPORTER_ASSERT(reporter, err != VK_TIMEOUT);
+
+ GR_VK_CALL(interface, DestroyFence(device, fence, nullptr));
+ GR_VK_CALL(interface, DestroySemaphore(device, vkSem, nullptr));
+ // If the above test fails the wait semaphore will never be signaled which can cause the
+ // device to hang when tearing down (even if just tearing down GL). So we Fail here to
+ // kill things.
+ if (err == VK_TIMEOUT) {
+ SkFAIL("Waiting on semaphore indefinitely");
+ }
+ }
+#endif
+}
+
#endif