Add command buffer submits before copy calls in vulkan.

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2363773006

Committed: https://skia.googlesource.com/skia/+/25661bac7722860b7589c5b01ec404531d941456
Review-Url: https://codereview.chromium.org/2363773006
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp
index 7669ba5..e72e723 100644
--- a/src/gpu/vk/GrVkCaps.cpp
+++ b/src/gpu/vk/GrVkCaps.cpp
@@ -19,6 +19,7 @@
     fMustDoCopiesFromOrigin = false;
     fAllowInitializationErrorOnTearDown = false;
     fSupportsCopiesAsDraws = false;
+    fMustSubmitCommandsBeforeCopyOp = false;
 
     /**************************************************************************
     * GrDrawTargetCaps fields
@@ -74,6 +75,11 @@
         fAllowInitializationErrorOnTearDown = true;
     }
 
+    if (kNvidia_VkVendor == properties.vendorID) {
+        fSupportsCopiesAsDraws = true;
+        fMustSubmitCommandsBeforeCopyOp = true;
+    }
+
     this->applyOptionsOverrides(contextOptions);
     GrGLSLCaps* glslCaps = static_cast<GrGLSLCaps*>(fShaderCaps.get());
     glslCaps->applyOptionsOverrides(contextOptions);
diff --git a/src/gpu/vk/GrVkCaps.h b/src/gpu/vk/GrVkCaps.h
index 8e8953e..a4ce35a 100644
--- a/src/gpu/vk/GrVkCaps.h
+++ b/src/gpu/vk/GrVkCaps.h
@@ -74,6 +74,10 @@
         return fSupportsCopiesAsDraws;
     }
 
+    bool mustSubmitCommandsBeforeCopyOp() const {
+        return fMustSubmitCommandsBeforeCopyOp;
+    }
+
     /**
      * Returns both a supported and most prefered stencil format to use in draws.
      */
@@ -86,6 +90,7 @@
 private:
     enum VkVendor {
         kQualcomm_VkVendor = 20803,
+        kNvidia_VkVendor = 4318,
     };
 
     void init(const GrContextOptions& contextOptions, const GrVkInterface* vkInterface,
@@ -135,6 +140,11 @@
     // Check whether we support using draws for copies.
     bool fSupportsCopiesAsDraws;
 
+    // On Nvidia there is a current bug where we must the current command buffer before copy
+    // operations or else the copy will not happen. This includes copies, blits, resolves, and copy
+    // as draws.
+    bool fMustSubmitCommandsBeforeCopyOp;
+
     typedef GrCaps INHERITED;
 };
 
diff --git a/src/gpu/vk/GrVkCommandBuffer.h b/src/gpu/vk/GrVkCommandBuffer.h
index 9864ec0..8020c7d 100644
--- a/src/gpu/vk/GrVkCommandBuffer.h
+++ b/src/gpu/vk/GrVkCommandBuffer.h
@@ -41,6 +41,8 @@
 
     void bindVertexBuffer(GrVkGpu* gpu, GrVkVertexBuffer* vbuffer) {
         VkBuffer vkBuffer = vbuffer->buffer();
+        // TODO: once vbuffer->offset() no longer always returns 0, we will need to track the offset
+        // to know if we can skip binding or not.
         if (!fBoundVertexBufferIsValid || vkBuffer != fBoundVertexBuffer) {
             VkDeviceSize offset = vbuffer->offset();
             GR_VK_CALL(gpu->vkInterface(), CmdBindVertexBuffers(fCmdBuffer,
@@ -56,6 +58,8 @@
 
     void bindIndexBuffer(GrVkGpu* gpu, GrVkIndexBuffer* ibuffer) {
         VkBuffer vkBuffer = ibuffer->buffer();
+        // TODO: once ibuffer->offset() no longer always returns 0, we will need to track the offset
+        // to know if we can skip binding or not.
         if (!fBoundIndexBufferIsValid || vkBuffer != fBoundIndexBuffer) {
             GR_VK_CALL(gpu->vkInterface(), CmdBindIndexBuffer(fCmdBuffer,
                                                               vkBuffer,
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index a72b517..c143219 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -380,6 +380,10 @@
     SkASSERT(dst);
     SkASSERT(src && src->numColorSamples() > 1 && src->msaaImage());
 
+    if (this->vkCaps().mustSubmitCommandsBeforeCopyOp()) {
+        this->submitCommandBuffer(GrVkGpu::kSkip_SyncQueue);
+    }
+
     // Flip rect if necessary
     SkIRect srcVkRect = srcRect;
     int32_t dstY = dstPoint.fY;
@@ -843,6 +847,10 @@
         return;
     }
 
+    if (this->vkCaps().mustSubmitCommandsBeforeCopyOp()) {
+        this->submitCommandBuffer(kSkip_SyncQueue);
+    }
+
     // We may need to resolve the texture first if it is also a render target
     GrVkRenderTarget* texRT = static_cast<GrVkRenderTarget*>(tex->asRenderTarget());
     if (texRT) {
@@ -1577,6 +1585,10 @@
         return true;
     }
 
+    if (this->vkCaps().mustSubmitCommandsBeforeCopyOp()) {
+        this->submitCommandBuffer(GrVkGpu::kSkip_SyncQueue);
+    }
+
     if (fCopyManager.copySurfaceAsDraw(this, dst, src, srcRect, dstPoint)) {
         return true;
     }
diff --git a/src/gpu/vk/GrVkVaryingHandler.cpp b/src/gpu/vk/GrVkVaryingHandler.cpp
index ac3a315..f6fed21 100644
--- a/src/gpu/vk/GrVkVaryingHandler.cpp
+++ b/src/gpu/vk/GrVkVaryingHandler.cpp
@@ -1,9 +1,9 @@
 /*
-* Copyright 2016 Google Inc.
-*
-* Use of this source code is governed by a BSD-style license that can be
-* found in the LICENSE file.
-*/
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
 
 #include "GrVkVaryingHandler.h"