Implement submit API to GrContext.

Change-Id: Ib813d42abb5f63e2ecdbf245d416658143853288
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/289033
Commit-Queue: Greg Daniel <egdaniel@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt
index 106ce20..fb0ef65 100644
--- a/RELEASE_NOTES.txt
+++ b/RELEASE_NOTES.txt
@@ -9,6 +9,16 @@
 
   * <insert new release notes here>
 
+  * GrContext submit is now required to be called in order to send GPU work to the
+    actual GPU. The flush calls simply produces 3D API specific objects that are ready
+    to be submitted (e.g. command buffers). For the GL backend, the flush will still
+    send commands to the driver. However, clients should still assume the must call
+    submit which is where any glFlush that is need for sync objects will be called. There,
+    are flushAndSubmit() functions of GrContext, SkSurface, and SkImage that will act
+    like the previous flush() functions. This will flush the work and immediately call
+    submit.
+    https://review.skia.org/289033
+
   * Remove deprecated version of flush calls on GrContext and SkSurface.
     https://review.skia.org/2290540
 
diff --git a/include/core/SkSurface.h b/include/core/SkSurface.h
index 99024e2..ca6c3cf 100644
--- a/include/core/SkSurface.h
+++ b/include/core/SkSurface.h
@@ -916,7 +916,8 @@
         Skia will correctly order its own draws and pixel operations. This must to be used to ensure
         correct ordering when the surface backing store is accessed outside Skia (e.g. direct use of
         the 3D API or a windowing system). GrContext has additional flush and submit methods that
-        apply to all surfaces and images created from a GrContext.
+        apply to all surfaces and images created from a GrContext. This is equivalent to calling
+        SkSurface::flush with a default GrFlushInfo followed by GrContext::submit.
     */
     void flushAndSubmit();
 
@@ -925,7 +926,16 @@
         kPresent,   //!< back-end surface will be used for presenting to screen
     };
 
-    /** Issues pending SkSurface commands to the GPU-backed API and resolves any SkSurface MSAA.
+    /** Issues pending SkSurface commands to the GPU-backed API objects and resolves any SkSurface
+        MSAA. A call to GrContext::submit is always required to ensure work is actually sent to the
+        gpu. Some specific API details:
+            GL: Commands are actually sent to the driver, but glFlush is never called. Thus some
+                sync objects from the flush will not be valid until a submission occurs.
+
+            Vulkan/Metal/D3D/Dawn: Commands are recorded to the backend APIs corresponding command
+                buffer or encoder objects. However, these objects are not sent to the gpu until a
+                submission occurs.
+
         The work that is submitted to the GPU will be dependent on the BackendSurfaceAccess that is
         passed in.
 
@@ -941,13 +951,19 @@
         The GrFlushInfo describes additional options to flush. Please see documentation at
         GrFlushInfo for more info.
 
-         If the return is GrSemaphoresSubmitted::kYes, only initialized GrBackendSemaphores will
-         have been submitted and can be waited on (it is possible Skia failed to create a subset of
-         the semaphores). If this call returns GrSemaphoresSubmitted::kNo, the GPU backend will not
-         have submitted any semaphores to be signaled on the GPU. Thus the client should not have
-         the GPU wait on any of the semaphores passed in with the GrFlushInfo. Regardless of whether
-         semaphores were submitted to the GPU or not, the client is still responsible for deleting
-         any initialized semaphores.
+        If the return is GrSemaphoresSubmitted::kYes, only initialized GrBackendSemaphores will be
+        submitted to the gpu during the next submit call (it is possible Skia failed to create a
+        subset of the semaphores). The client should not wait on these semaphores until after submit
+        has been called, but must keep them alive until then. If a submit flag was passed in with
+        the flush these valid semaphores can we waited on immediately. If this call returns
+        GrSemaphoresSubmitted::kNo, the GPU backend will not submit any semaphores to be signaled on
+        the GPU. Thus the client should not have the GPU wait on any of the semaphores passed in
+        with the GrFlushInfo. Regardless of whether semaphores were submitted to the GPU or not, the
+        client is still responsible for deleting any initialized semaphores.
+        Regardleess of semaphore submission the context will still be flushed. It should be
+        emphasized that a return value of GrSemaphoresSubmitted::kNo does not mean the flush did not
+        happen. It simply means there were no semaphores submitted to the GPU. A caller should only
+        take this as a failure if they passed in semaphores to be submitted.
 
         Pending surface commands are flushed regardless of the return result.
 
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h
index aaf1c6d..54ac55b 100644
--- a/include/gpu/GrContext.h
+++ b/include/gpu/GrContext.h
@@ -296,7 +296,6 @@
     ///////////////////////////////////////////////////////////////////////////
     // Misc.
 
-
     /**
      * Inserts a list of GPU semaphores that the current GPU-backed API must wait on before
      * executing any more commands on the GPU. Skia will take ownership of the underlying semaphores
@@ -307,20 +306,35 @@
     bool wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores);
 
     /**
-     * Call to ensure all drawing to the context has been issued to the underlying 3D API.
+     * Call to ensure all drawing to the context has been flushed and submitted to the underlying 3D
+     * API. This is equivalent to calling GrContext::flush with a default GrFlushInfo followed by
+     * GrContext::submit.
      */
-    void flushAndSubmit() { this->flush(GrFlushInfo(), GrPrepareForExternalIORequests()); }
+    void flushAndSubmit() {
+        this->flush(GrFlushInfo(), GrPrepareForExternalIORequests());
+        this->submit();
+    }
 
     /**
-     * Call to ensure all drawing to the context has been issued to the underlying 3D API.
+     * Call to ensure all drawing to the context has been flushed to underlying 3D API specific
+     * objects. A call to GrContext::submit is always required to ensure work is actually sent to
+     * the gpu. Some specific API details:
+     *     GL: Commands are actually sent to the driver, but glFlush is never called. Thus some
+     *         sync objects from the flush will not be valid until a submission occurs.
      *
-     * If the return is GrSemaphoresSubmitted::kYes, only initialized GrBackendSemaphores will have
-     * been submitted and can be waited on (it is possible Skia failed to create a subset of the
-     * semaphores). If this call returns GrSemaphoresSubmitted::kNo, the GPU backend will not have
-     * submitted any semaphores to be signaled on the GPU. Thus the client should not have the GPU
-     * wait on any of the semaphores passed in with the GrFlushInfo. Regardless of whether
-     * semaphores were submitted to the GPU or not, the client is still responsible for deleting any
-     * initialized semaphores.
+     *     Vulkan/Metal/D3D/Dawn: Commands are recorded to the backend APIs corresponding command
+     *         buffer or encoder objects. However, these objects are not sent to the gpu until a
+     *         submission occurs.
+     *
+     * If the return is GrSemaphoresSubmitted::kYes, only initialized GrBackendSemaphores will be
+     * submitted to the gpu during the next submit call (it is possible Skia failed to create a
+     * subset of the semaphores). The client should not wait on these semaphores until after submit
+     * has been called, but must keep them alive until then. If a submit flag was passed in with the
+     * flush these valid semaphores can we waited on immediately. If this call returns
+     * GrSemaphoresSubmitted::kNo, the GPU backend will not submit any semaphores to be signaled on
+     * the GPU. Thus the client should not have the GPU wait on any of the semaphores passed in with
+     * the GrFlushInfo. Regardless of whether semaphores were submitted to the GPU or not, the
+     * client is still responsible for deleting any initialized semaphores.
      * Regardleess of semaphore submission the context will still be flushed. It should be
      * emphasized that a return value of GrSemaphoresSubmitted::kNo does not mean the flush did not
      * happen. It simply means there were no semaphores submitted to the GPU. A caller should only
@@ -331,26 +345,54 @@
     }
 
     /**
-     * Call to ensure all drawing to the context has been issued to the underlying 3D API.
+     * Call to ensure all drawing to the context has been flushed to underlying 3D API specific
+     * objects. A call to GrContext::submit is always required to ensure work is actually sent to
+     * the gpu. Some specific API details:
+     *     GL: Commands are actually sent to the driver, but glFlush is never called. Thus some
+     *         sync objects from the flush will not be valid until submit is called.
      *
-     * If this call returns GrSemaphoresSubmitted::kNo, the GPU backend will not have created or
-     * added any semaphores to signal on the GPU. Thus the client should not have the GPU wait on
-     * any of the semaphores passed in with the GrFlushInfo. However, any pending commands to the
-     * context will still be flushed. It should be emphasized that a return value of
-     * GrSemaphoresSubmitted::kNo does not mean the flush did not happen. It simply means there were
-     * no semaphores submitted to the GPU. A caller should only take this as a failure if they
-     * passed in semaphores to be submitted.
+     *     Vulkan/Metal/D3D/Dawn: Commands are recorded to the backend APIs corresponding command
+     *         buffer or encoder objects. However, these objects are not sent to the gpu until
+     *         submit is called.
+     *
+     * Note: The default values for GrFlushInfo will submit the work the gpu.
+     *
+     * If the return is GrSemaphoresSubmitted::kYes, only initialized GrBackendSemaphores will be
+     * submitted to the gpu during the next submit call (it is possible Skia failed to create a
+     * subset of the semaphores). The client should not wait on these semaphores until after submit
+     * has been called, but must keep them alive until then. If this call returns
+     * GrSemaphoresSubmitted::kNo, the GPU backend will not submit any semaphores to be signaled on
+     * the GPU. Thus the client should not have the GPU wait on any of the semaphores passed in with
+     * the GrFlushInfo. The client is always responsible for deleting any initialized semaphores.
+     * Regardleess of semaphore submission the context will still be flushed. It should be
+     * emphasized that a return value of GrSemaphoresSubmitted::kNo does not mean the flush did not
+     * happen. It simply means there were no semaphores submitted to the GPU. A caller should only
+     * take this as a failure if they passed in semaphores to be submitted.
      *
      * If the GrPrepareForExternalIORequests contains valid gpu backed SkSurfaces or SkImages, Skia
      * will put the underlying backend objects into a state that is ready for external uses. See
-     * declaration of GrPreopareForExternalIORequests for more details.
+     * declaration of GrPreopareForExternalIORequests for more details. Note that the backend
+     * objects will not be moved to this state until submit has been called. If subsequent flushes
+     * are called between this and submit, those objects are no longer guaranteed to be in a state
+     * that is ready for external use.
      */
     GrSemaphoresSubmitted flush(const GrFlushInfo&, const GrPrepareForExternalIORequests&);
 
     /**
-     * Placeholder no-op submit call.
+     * Submit outstanding work to the gpu from all previously un-submitted flushes. The return
+     * value of the submit will indicate whether or not the submission to the GPU was successful.
+     *
+     * If the call returns true, all previously passed in semaphores in flush calls will have been
+     * submitted to the GPU and they can safely be waited on. The caller should wait on those
+     * semaphores or perform some other global synchronization before deleting the semaphores.
+     *
+     * If it returns false, then those same semaphores will not have been submitted and we will not
+     * try to submit them again. The caller is free to delete the semaphores at any time.
+     *
+     * If the syncCpu flag is true this function will return once the gpu has finished with all
+     * submitted work.
      */
-    bool submit(bool syncToCpu = false);
+    bool submit(bool syncCpu = false);
 
     /**
      * Checks whether any asynchronous work is complete and if so calls related callbacks.
diff --git a/include/gpu/GrTypes.h b/include/gpu/GrTypes.h
index e7d4f7e..8380a05 100644
--- a/include/gpu/GrTypes.h
+++ b/include/gpu/GrTypes.h
@@ -227,7 +227,7 @@
 
 enum GrFlushFlags {
     kNone_GrFlushFlags = 0,
-    // flush will wait till all submitted GPU work is finished before returning.
+    // Deprecated: Use syncCpu call on submit instead.
     kSyncCpu_GrFlushFlag = 0x1,
 };
 
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 291c434..88307ba 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -319,21 +319,26 @@
         return GrSemaphoresSubmitted::kNo;
     }
 
-    bool submitted = false;
-    if (this->drawingManager()->flush(nullptr, 0, SkSurface::BackendSurfaceAccess::kNoAccess,
-                                      info, externalRequests)) {
-        bool forceSync = SkToBool(info.fFlags & kSyncCpu_GrFlushFlag);
-        submitted = this->drawingManager()->submitToGpu(forceSync);
-    }
+    bool flushed = this->drawingManager()->flush(
+            nullptr, 0, SkSurface::BackendSurfaceAccess::kNoAccess, info, externalRequests);
 
-    if (!submitted || (!this->priv().caps()->semaphoreSupport() && info.fNumSemaphores)) {
+    if (!flushed || (!this->priv().caps()->semaphoreSupport() && info.fNumSemaphores)) {
         return GrSemaphoresSubmitted::kNo;
     }
     return GrSemaphoresSubmitted::kYes;
 }
 
-bool GrContext::submit(bool syncToCpu) {
-    return true;
+bool GrContext::submit(bool syncCpu) {
+    ASSERT_SINGLE_OWNER
+    if (this->abandoned()) {
+        return false;
+    }
+
+    if (!fGpu) {
+        return false;
+    }
+
+    return fGpu->submitToGpu(syncCpu);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp
index 2502d08..badb958 100644
--- a/src/gpu/GrDrawingManager.cpp
+++ b/src/gpu/GrDrawingManager.cpp
@@ -570,12 +570,7 @@
 
     SkDEBUGCODE(this->validate());
 
-    bool submitted = false;
-    if (didFlush) {
-        submitted = this->submitToGpu(SkToBool(info.fFlags & kSyncCpu_GrFlushFlag));
-    }
-
-    if (!submitted || (!direct->priv().caps()->semaphoreSupport() && info.fNumSemaphores)) {
+    if (!didFlush || (!direct->priv().caps()->semaphoreSupport() && info.fNumSemaphores)) {
         return GrSemaphoresSubmitted::kNo;
     }
     return GrSemaphoresSubmitted::kYes;
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index 33ebf96..5c3dc0f 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -1901,6 +1901,7 @@
     flushInfo.fFinishedContext = finishContext;
     flushInfo.fFinishedProc = finishCallback;
     this->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo);
+    directContext->submit();
 }
 
 void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,
@@ -2153,6 +2154,7 @@
     flushInfo.fFinishedContext = finishContext;
     flushInfo.fFinishedProc = finishCallback;
     this->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo);
+    direct->submit();
 }
 
 GrSemaphoresSubmitted GrRenderTargetContext::flush(SkSurface::BackendSurfaceAccess access,
diff --git a/src/gpu/GrSurfaceContext.cpp b/src/gpu/GrSurfaceContext.cpp
index ea0b2eb..3549e1a 100644
--- a/src/gpu/GrSurfaceContext.cpp
+++ b/src/gpu/GrSurfaceContext.cpp
@@ -275,7 +275,7 @@
     }
 
     direct->priv().flushSurface(srcProxy);
-
+    direct->submit();
     if (!direct->priv().getGpu()->readPixels(srcSurface, pt.fX, pt.fY, dstInfo.width(),
                                              dstInfo.height(), this->colorInfo().colorType(),
                                              supportedRead.fColorType, readDst, readRB)) {
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index df273f6..b316059 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1061,6 +1061,7 @@
 
 void SkGpuDevice::flush() {
     this->flush(SkSurface::BackendSurfaceAccess::kNoAccess, GrFlushInfo());
+    this->context()->submit();
 }
 
 GrSemaphoresSubmitted SkGpuDevice::flush(SkSurface::BackendSurfaceAccess access,
diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp
index 1a10497..9aba1e3 100644
--- a/src/image/SkImage.cpp
+++ b/src/image/SkImage.cpp
@@ -160,7 +160,10 @@
     return as_IB(this)->onFlush(context, flushInfo);
 }
 
-void SkImage::flushAndSubmit(GrContext* context) { this->flush(context, {}); }
+void SkImage::flushAndSubmit(GrContext* context) {
+    this->flush(context, {});
+    context->submit();
+}
 
 #else
 
diff --git a/src/image/SkSurface.cpp b/src/image/SkSurface.cpp
index 77269a8..361d9b6 100644
--- a/src/image/SkSurface.cpp
+++ b/src/image/SkSurface.cpp
@@ -444,10 +444,6 @@
                                                releaseContext);
 }
 
-void SkSurface::flushAndSubmit() {
-    this->flush(BackendSurfaceAccess::kNoAccess, GrFlushInfo());
-}
-
 GrSemaphoresSubmitted SkSurface::flush(BackendSurfaceAccess access, const GrFlushInfo& flushInfo) {
     return asSB(this)->onFlush(access, flushInfo);
 }
@@ -537,4 +533,8 @@
     return nullptr;
 }
 
+void SkSurface::flushAndSubmit() {
+    this->flush(BackendSurfaceAccess::kNoAccess, GrFlushInfo());
+}
+
 #endif
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
index 173af27..be5a2b6 100644
--- a/src/image/SkSurface_Gpu.cpp
+++ b/src/image/SkSurface_Gpu.cpp
@@ -732,4 +732,10 @@
 }
 #endif
 
+void SkSurface::flushAndSubmit() {
+    this->flush(BackendSurfaceAccess::kNoAccess, GrFlushInfo());
+    SkASSERT(this->getContext());
+    this->getContext()->submit();
+}
+
 #endif
diff --git a/tests/ImageTest.cpp b/tests/ImageTest.cpp
index bbc1bdb..3b67073 100644
--- a/tests/ImageTest.cpp
+++ b/tests/ImageTest.cpp
@@ -1379,55 +1379,55 @@
     // Flush all the setup work we did above and then make little lambda that reports the flush
     // count delta since the last time it was called.
     c->flushAndSubmit();
-    auto numFlushes = [c, flushCnt = c->priv().getGpu()->stats()->numSubmitToGpus()]() mutable {
+    auto numSubmits = [c, submitCnt = c->priv().getGpu()->stats()->numSubmitToGpus()]() mutable {
         int curr = c->priv().getGpu()->stats()->numSubmitToGpus();
-        int n = curr - flushCnt;
-        flushCnt = curr;
+        int n = curr - submitCnt;
+        submitCnt = curr;
         return n;
     };
 
-    // Images aren't used therefore flush is ignored.
+    // Images aren't used therefore flush is ignored, but submit is still called.
     i0->flushAndSubmit(c);
     i1->flushAndSubmit(c);
     i2->flushAndSubmit(c);
-    REPORTER_ASSERT(reporter, numFlushes() == 0);
+    REPORTER_ASSERT(reporter, numSubmits() == 3);
 
     // Syncing forces the flush to happen even if the images aren't used.
     GrFlushInfo syncInfo;
     syncInfo.fFlags = kSyncCpu_GrFlushFlag;
     i0->flush(c, syncInfo);
     c->submit(true);
-    REPORTER_ASSERT(reporter, numFlushes() == 1);
+    REPORTER_ASSERT(reporter, numSubmits() == 1);
     i1->flush(c, syncInfo);
     c->submit(true);
-    REPORTER_ASSERT(reporter, numFlushes() == 1);
+    REPORTER_ASSERT(reporter, numSubmits() == 1);
     i2->flush(c, syncInfo);
     c->submit(true);
-    REPORTER_ASSERT(reporter, numFlushes() == 1);
+    REPORTER_ASSERT(reporter, numSubmits() == 1);
 
     // Use image 1
     s->getCanvas()->drawImage(i1, 0, 0);
-    // Flushing image 0 should do nothing.
+    // Flushing image 0 should do nothing, but submit is still called.
     i0->flushAndSubmit(c);
-    REPORTER_ASSERT(reporter, numFlushes() == 0);
+    REPORTER_ASSERT(reporter, numSubmits() == 1);
     // Flushing image 1 should flush.
     i1->flushAndSubmit(c);
-    REPORTER_ASSERT(reporter, numFlushes() == 1);
-    // Flushing image 2 should do nothing.
+    REPORTER_ASSERT(reporter, numSubmits() == 1);
+    // Flushing image 2 should do nothing, but submit is still called.
     i2->flushAndSubmit(c);
-    REPORTER_ASSERT(reporter, numFlushes() == 0);
+    REPORTER_ASSERT(reporter, numSubmits() == 1);
 
     // Use image 2
     s->getCanvas()->drawImage(i2, 0, 0);
-    // Flushing image 0 should do nothing.
+    // Flushing image 0 should do nothing, but submit is still called.
     i0->flushAndSubmit(c);
-    REPORTER_ASSERT(reporter, numFlushes() == 0);
-    // Flushing image 1 do nothing.
+    REPORTER_ASSERT(reporter, numSubmits() == 1);
+    // Flushing image 1 do nothing, but submit is still called.
     i1->flushAndSubmit(c);
-    REPORTER_ASSERT(reporter, numFlushes() == 0);
+    REPORTER_ASSERT(reporter, numSubmits() == 1);
     // Flushing image 2 should flush.
     i2->flushAndSubmit(c);
-    REPORTER_ASSERT(reporter, numFlushes() == 1);
+    REPORTER_ASSERT(reporter, numSubmits() == 1);
     // Since we just did a simple image draw it should not have been flattened.
     REPORTER_ASSERT(reporter,
                     !static_cast<SkImage_GpuYUVA*>(as_IB(i2.get()))->testingOnly_IsFlattened());
@@ -1439,35 +1439,35 @@
                     static_cast<SkImage_GpuYUVA*>(as_IB(i2.get()))->testingOnly_IsFlattened());
     REPORTER_ASSERT(reporter, static_cast<SkImage_GpuYUVA*>(as_IB(i2.get()))->isTextureBacked());
     s->getCanvas()->drawImage(i2, 0, 0);
-    // Flushing image 0 should do nothing.
+    // Flushing image 0 should do nothing, but submit is still called.
     i0->flushAndSubmit(c);
-    REPORTER_ASSERT(reporter, numFlushes() == 0);
-    // Flushing image 1 do nothing.
+    REPORTER_ASSERT(reporter, numSubmits() == 1);
+    // Flushing image 1 do nothing, but submit is still called.
     i1->flushAndSubmit(c);
-    REPORTER_ASSERT(reporter, numFlushes() == 0);
+    REPORTER_ASSERT(reporter, numSubmits() == 1);
     // Flushing image 2 should flush.
     i2->flushAndSubmit(c);
-    REPORTER_ASSERT(reporter, numFlushes() == 1);
+    REPORTER_ASSERT(reporter, numSubmits() == 1);
 
     // Test case where flatten happens before the first flush.
     i2 = make_yuva_image(c);
     // On some systems where preferVRAMUseOverFlushes is false (ANGLE on Windows) the above may
     // actually flush in order to make textures for the YUV planes. TODO: Remove this when we
     // make the YUVA planes from backend textures rather than pixmaps that GrContext must upload.
-    // Calling numFlushes rebases the flush count from here.
-    numFlushes();
+    // Calling numSubmits rebases the flush count from here.
+    numSubmits();
     as_IB(i2.get())->view(c);
     REPORTER_ASSERT(reporter,
                     static_cast<SkImage_GpuYUVA*>(as_IB(i2.get()))->testingOnly_IsFlattened());
     REPORTER_ASSERT(reporter, static_cast<SkImage_GpuYUVA*>(as_IB(i2.get()))->isTextureBacked());
     s->getCanvas()->drawImage(i2, 0, 0);
-    // Flushing image 0 should do nothing.
+    // Flushing image 0 should do nothing, but submit is still called.
     i0->flushAndSubmit(c);
-    REPORTER_ASSERT(reporter, numFlushes() == 0);
-    // Flushing image 1 do nothing.
+    REPORTER_ASSERT(reporter, numSubmits() == 1);
+    // Flushing image 1 do nothing, but submit is still called.
     i1->flushAndSubmit(c);
-    REPORTER_ASSERT(reporter, numFlushes() == 0);
-    // Flushing image 2 should flush.
+    REPORTER_ASSERT(reporter, numSubmits() == 1);
+    // Flushing image 2 should flush, but submit is still called.
     i2->flushAndSubmit(c);
-    REPORTER_ASSERT(reporter, numFlushes() == 1);
+    REPORTER_ASSERT(reporter, numSubmits() == 1);
 }
diff --git a/tests/SurfaceSemaphoreTest.cpp b/tests/SurfaceSemaphoreTest.cpp
index 787d2c4..91519ed 100644
--- a/tests/SurfaceSemaphoreTest.cpp
+++ b/tests/SurfaceSemaphoreTest.cpp
@@ -245,9 +245,10 @@
     GrFlushInfo flushInfo;
     flushInfo.fNumSemaphores = 1;
     flushInfo.fSignalSemaphores = &semaphore;
-    GrSemaphoresSubmitted submitted = mainSurface->flush(SkSurface::BackendSurfaceAccess::kNoAccess,
-                                                         flushInfo);
+    GrSemaphoresSubmitted submitted =
+            mainSurface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo);
     REPORTER_ASSERT(reporter, GrSemaphoresSubmitted::kYes == submitted);
+    ctx->submit();
 
 #ifdef SK_GL
     if (GrBackendApi::kOpenGL == ctxInfo.backend()) {