Separate GrCaps for semaphores and fence syncs.

GrGpu implements CPU/GPU synchronization using GrFence and GPU/GPU
synchronization using GrSemaphore. However, it currently uses one cap,
fenceSyncSupport(), to check for availability of both.

This change separates these caps.

Change-Id: I3e976c7f8e5355c0c212c8de3cc8d8cb77d921d7
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/212720
Reviewed-by: Greg Daniel <egdaniel@google.com>
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/GrCaps.cpp b/src/gpu/GrCaps.cpp
index d3f6374..7543820 100644
--- a/src/gpu/GrCaps.cpp
+++ b/src/gpu/GrCaps.cpp
@@ -36,6 +36,7 @@
     fShouldInitializeTextures = false;
     fSupportsAHardwareBufferImages = false;
     fFenceSyncSupport = false;
+    fSemaphoreSupport = false;
     fCrossContextTextureSupport = false;
     fHalfFloatVertexAttributeSupport = false;
     fDynamicStateArrayGeometryProcessorTextureSupport = false;
@@ -210,6 +211,7 @@
     writer->appendBool("Should initialize textures", fShouldInitializeTextures);
     writer->appendBool("Supports importing AHardwareBuffers", fSupportsAHardwareBufferImages);
     writer->appendBool("Fence sync support", fFenceSyncSupport);
+    writer->appendBool("Semaphore support", fSemaphoreSupport);
     writer->appendBool("Cross context texture support", fCrossContextTextureSupport);
     writer->appendBool("Half float vertex attribute support", fHalfFloatVertexAttributeSupport);
     writer->appendBool("Specify GeometryProcessor textures as a dynamic state array",
diff --git a/src/gpu/GrCaps.h b/src/gpu/GrCaps.h
index e6518fb..9dd739c 100644
--- a/src/gpu/GrCaps.h
+++ b/src/gpu/GrCaps.h
@@ -263,7 +263,12 @@
 
     bool wireframeMode() const { return fWireframeMode; }
 
+    /** Supports using GrFence. */
     bool fenceSyncSupport() const { return fFenceSyncSupport; }
+
+    /** Supports using GrSemaphore. */
+    bool semaphoreSupport() const { return fSemaphoreSupport; }
+
     bool crossContextTextureSupport() const { return fCrossContextTextureSupport; }
     /**
      * Returns whether or not we will be able to do a copy given the passed in params
@@ -391,8 +396,8 @@
     // On some platforms it's better to make more triangles than to use the sample mask (MSAA only).
     bool fPreferTrianglesOverSampleMask              : 1;
 
-    // TODO: this may need to be an enum to support different fence types
     bool fFenceSyncSupport                           : 1;
+    bool fSemaphoreSupport                           : 1;
 
     // Requires fence sync support in GL.
     bool fCrossContextTextureSupport                 : 1;
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 112e2aa..a90dce9 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -244,7 +244,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 bool GrContext::wait(int numSemaphores, const GrBackendSemaphore waitSemaphores[]) {
-    if (!fGpu || fGpu->caps()->fenceSyncSupport()) {
+    if (!fGpu || fGpu->caps()->semaphoreSupport()) {
         return false;
     }
     for (int i = 0; i < numSemaphores; ++i) {
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index 811f8d3..c57b169 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -418,7 +418,7 @@
     this->stats()->incNumFinishFlushes();
     GrResourceProvider* resourceProvider = fContext->priv().resourceProvider();
 
-    if (this->caps()->fenceSyncSupport()) {
+    if (this->caps()->semaphoreSupport()) {
         for (int i = 0; i < info.fNumSemaphores; ++i) {
             sk_sp<GrSemaphore> semaphore;
             if (info.fSignalSemaphores[i].isInitialized()) {
@@ -437,7 +437,7 @@
         }
     }
     this->onFinishFlush(proxy, access, info);
-    return this->caps()->fenceSyncSupport() ? GrSemaphoresSubmitted::kYes
+    return this->caps()->semaphoreSupport() ? GrSemaphoresSubmitted::kYes
                                             : GrSemaphoresSubmitted::kNo;
 }
 
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index 5ad3aae..977e96f 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -1756,7 +1756,7 @@
 
     AutoCheckFlush acf(this->drawingManager());
 
-    if (numSemaphores && !this->caps()->fenceSyncSupport()) {
+    if (numSemaphores && !this->caps()->semaphoreSupport()) {
         return false;
     }
 
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index c22daa1..e5cb3f3 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -627,9 +627,12 @@
         // Only in WebGL 2.0
         fFenceSyncSupport = version >= GR_GL_VER(2, 0);
     }
+    // The same objects (GL sync objects) are used to implement GPU/CPU fence syncs and GPU/GPU
+    // semaphores.
+    fSemaphoreSupport = fFenceSyncSupport;
 
-    // Safely moving textures between contexts requires fences.
-    fCrossContextTextureSupport = fFenceSyncSupport;
+    // Safely moving textures between contexts requires semaphores.
+    fCrossContextTextureSupport = fSemaphoreSupport;
 
     // Half float vertex attributes requires GL3 or ES3
     // It can also work with OES_VERTEX_HALF_FLOAT, but that requires a different enum.
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index ec2f370..197a1a6 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -4277,7 +4277,7 @@
 void GrGLGpu::onFinishFlush(GrSurfaceProxy*, SkSurface::BackendSurfaceAccess access,
                             const GrFlushInfo& info) {
     // If we inserted semaphores during the flush, we need to call GLFlush.
-    bool insertedSemaphore = info.fNumSemaphores > 0 && this->caps()->fenceSyncSupport();
+    bool insertedSemaphore = info.fNumSemaphores > 0 && this->caps()->semaphoreSupport();
     // We call finish if the client told us to sync or if we have a finished proc but don't support
     // GLsync objects.
     bool finish = (info.fFlags & kSyncCpu_GrFlushFlag) ||
@@ -4344,14 +4344,14 @@
 }
 
 sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT GrGLGpu::makeSemaphore(bool isOwned) {
-    SkASSERT(this->caps()->fenceSyncSupport());
+    SkASSERT(this->caps()->semaphoreSupport());
     return GrGLSemaphore::Make(this, isOwned);
 }
 
 sk_sp<GrSemaphore> GrGLGpu::wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
                                                  GrResourceProvider::SemaphoreWrapType wrapType,
                                                  GrWrapOwnership ownership) {
-    SkASSERT(this->caps()->fenceSyncSupport());
+    SkASSERT(this->caps()->semaphoreSupport());
     return GrGLSemaphore::MakeWrapped(this, semaphore.glSync(), ownership);
 }
 
diff --git a/src/gpu/mtl/GrMtlCaps.mm b/src/gpu/mtl/GrMtlCaps.mm
index 4344b39..08018aa 100644
--- a/src/gpu/mtl/GrMtlCaps.mm
+++ b/src/gpu/mtl/GrMtlCaps.mm
@@ -32,6 +32,7 @@
     // The following are disabled due to the unfinished Metal backend, not because Metal itself
     // doesn't support it.
     fFenceSyncSupport = false;           // Fences are not implemented yet
+    fSemaphoreSupport = false;           // Semaphores are not implemented yet
     fMultisampleDisableSupport = true;   // MSAA and resolving not implemented yet
     fDiscardRenderTargetSupport = false; // GrMtlGpuCommandBuffer::discard() not implemented
     fCrossContextTextureSupport = false; // GrMtlGpu::prepareTextureForCrossContextUsage() not impl
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp
index acc4f8f..76230a1 100644
--- a/src/gpu/vk/GrVkCaps.cpp
+++ b/src/gpu/vk/GrVkCaps.cpp
@@ -36,6 +36,7 @@
     fOversizedStencilSupport = false; //TODO: figure this out
     fInstanceAttribSupport = true;
 
+    fSemaphoreSupport = true;   // always available in Vulkan
     fFenceSyncSupport = true;   // always available in Vulkan
     fCrossContextTextureSupport = true;
     fHalfFloatVertexAttributeSupport = true;