From cd1416efbc7af6f115dbaa09dce48e075d1d96ca Mon Sep 17 00:00:00 2001 From: Greg Daniel Date: Fri, 21 Jul 2017 14:27:57 -0400 Subject: Add support for semaphores to be inserted on GrContext flush This also moves the logic of inserting semaphores down into GrDrawingManager and finishFlush on GrGpu. With it being on finishFlush, there should be no issues when the DrawingManager starts respecting the proxy passed in assuming it always calls finishFlush at the end (which it should). Bug: skia: Change-Id: I925c2a289dcbbb9159b9120878af1d34f21a2dc7 Reviewed-on: https://skia-review.googlesource.com/25641 Reviewed-by: Brian Salomon Commit-Queue: Greg Daniel --- include/core/SkSurface.h | 14 +++++++--- include/gpu/GrBackendSemaphore.h | 7 +++++ include/gpu/GrContext.h | 30 ++++++++++++++++++-- src/gpu/GrContext.cpp | 11 +++++++- src/gpu/GrDrawingManager.cpp | 25 +++++++++++------ src/gpu/GrDrawingManager.h | 18 ++++++++---- src/gpu/GrGpu.cpp | 25 +++++++++++++++++ src/gpu/GrGpu.h | 10 +++++-- src/gpu/GrRenderTargetContext.cpp | 38 ++++--------------------- src/gpu/GrRenderTargetContext.h | 3 +- src/gpu/GrSemaphore.h | 1 + src/gpu/SkGpuDevice.cpp | 4 +-- src/gpu/SkGpuDevice.h | 3 +- src/gpu/gl/GrGLGpu.cpp | 8 +++++- src/gpu/gl/GrGLGpu.h | 2 ++ src/gpu/mock/GrMockGpu.h | 2 ++ src/gpu/mtl/GrMtlGpu.h | 2 ++ src/gpu/vk/GrVkCopyManager.cpp | 2 +- src/gpu/vk/GrVkGpu.cpp | 5 ++-- src/gpu/vk/GrVkGpu.h | 4 +-- src/image/SkSurface.cpp | 3 +- src/image/SkSurface_Base.h | 5 ++-- src/image/SkSurface_Gpu.cpp | 3 +- src/image/SkSurface_Gpu.h | 3 +- tests/SurfaceSemaphoreTest.cpp | 58 +++++++++++++++++++++++---------------- 25 files changed, 193 insertions(+), 93 deletions(-) diff --git a/include/core/SkSurface.h b/include/core/SkSurface.h index 4a8d81205f..d977391442 100644 --- a/include/core/SkSurface.h +++ b/include/core/SkSurface.h @@ -18,6 +18,7 @@ class GrBackendRenderTarget; class GrBackendSemaphore; class GrContext; class GrRenderTarget; +enum class GrSemaphoresSubmitted; /** * SkSurface is responsible for managing the pixels that a canvas draws into. The pixels can be @@ -329,16 +330,21 @@ public: * If it is not initialized, a new semaphore is created and the GrBackendSemaphore object * is initialized with that semaphore. * + * The client will own and be responsible for deleting the underlying semaphores that are stored + * and returned in initialized GrBackendSemaphore objects. The GrBackendSemaphore objects + * themselves can be deleted as soon as this function returns. + * * If the backend API is OpenGL only uninitialized GrBackendSemaphores are supported. * If the backend API is Vulkan either initialized or unitialized semaphores are supported. * If unitialized, the semaphores which are created will be valid for use only with the VkDevice * with which they were created. * - * If this call returns false, the GPU backend will not have created or added any semaphores to - * signal. Thus the array of semaphores will remain uninitialized. However, any pending surface - * IO will still be flush. + * If this call returns GrSemaphoresSubmited::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. However, any pending surface IO will still be flushed. */ - bool flushAndSignalSemaphores(int numSemaphores, GrBackendSemaphore* signalSemaphores); + GrSemaphoresSubmitted flushAndSignalSemaphores(int numSemaphores, + GrBackendSemaphore signalSemaphores[]); /** * Inserts a list of GPU semaphores that the current backend 3D API must wait on before diff --git a/include/gpu/GrBackendSemaphore.h b/include/gpu/GrBackendSemaphore.h index 5c41532cb9..cea3745270 100644 --- a/include/gpu/GrBackendSemaphore.h +++ b/include/gpu/GrBackendSemaphore.h @@ -16,6 +16,13 @@ #include "vk/GrVkTypes.h" #endif +// Enum used as return value when flush with semaphores so the client knows whether the +// semaphores were submitted to GPU or not. +enum class GrSemaphoresSubmitted { + kNo, + kYes, +}; + /** * Wrapper class for passing into and receiving data from Ganesh about a backend semaphore object. */ diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h index f48b8db710..46a9008b63 100644 --- a/include/gpu/GrContext.h +++ b/include/gpu/GrContext.h @@ -17,6 +17,7 @@ #include "../private/GrSingleOwner.h" class GrAtlasGlyphCache; +class GrBackendSemaphore; struct GrContextOptions; class GrContextPriv; class GrContextThreadSafeProxy; @@ -43,6 +44,8 @@ class SkTraceMemoryDump; class SkImage; class SkSurfaceProps; +enum class GrSemaphoresSubmitted; + class SK_API GrContext : public SkRefCnt { public: /** @@ -237,11 +240,34 @@ public: // Misc. /** - * 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 issued to the underlying 3D API. */ void flush(); + /** + * Call to ensure all drawing to the context has been issued to the underlying 3D API. After + * issuing all commands, numSemaphore semaphores will be signaled by the gpu. The client passes + * in an array of numSemaphores GrBackendSemaphores. In general these GrBackendSemaphore's can + * be either initialized or not. If they are initialized, the backend uses the passed in + * semaphore. If it is not initialized, a new semaphore is created and the GrBackendSemaphore + * object is initialized with that semaphore. + * + * The client will own and be responsible for deleting the underlying semaphores that are stored + * and returned in initialized GrBackendSemaphore objects. The GrBackendSemaphore objects + * themselves can be deleted as soon as this function returns. + * + * If the backend API is OpenGL only uninitialized GrBackendSemaphores are supported. + * If the backend API is Vulkan either initialized or unitialized semaphores are supported. + * If unitialized, the semaphores which are created will be valid for use only with the VkDevice + * with which they were created. + * + * If this call returns GrSemaphoresSubmited::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. However, any pending commands to the context will still be flushed. + */ + GrSemaphoresSubmitted flushAndSignalSemaphores(int numSemaphores, + GrBackendSemaphore signalSemaphores[]); + /** * An ID associated with this context, guaranteed to be unique. */ diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 88fe379c37..6abfb6ae21 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -5,6 +5,7 @@ * found in the LICENSE file. */ +#include "GrBackendSemaphore.h" #include "GrContext.h" #include "GrClip.h" #include "GrContextOptions.h" @@ -265,6 +266,14 @@ void GrContext::flush() { fDrawingManager->flush(nullptr); } +GrSemaphoresSubmitted GrContext::flushAndSignalSemaphores(int numSemaphores, + GrBackendSemaphore signalSemaphores[]) { + ASSERT_SINGLE_OWNER + if (fDrawingManager->wasAbandoned()) { return GrSemaphoresSubmitted::kNo; } + + return fDrawingManager->flush(nullptr, numSemaphores, signalSemaphores); +} + void GrContextPriv::flush(GrSurfaceProxy* proxy) { ASSERT_SINGLE_OWNER_PRIV RETURN_IF_ABANDONED_PRIV @@ -597,7 +606,7 @@ void GrContextPriv::prepareSurfaceForExternalIO(GrSurfaceProxy* proxy) { RETURN_IF_ABANDONED_PRIV SkASSERT(proxy); ASSERT_OWNED_PROXY_PRIV(proxy); - fContext->fDrawingManager->prepareSurfaceForExternalIO(proxy); + fContext->fDrawingManager->prepareSurfaceForExternalIO(proxy, 0, nullptr); } void GrContextPriv::flushSurfaceWrites(GrSurfaceProxy* proxy) { diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp index eeb107118c..8de2471cac 100644 --- a/src/gpu/GrDrawingManager.cpp +++ b/src/gpu/GrDrawingManager.cpp @@ -7,6 +7,7 @@ #include "GrDrawingManager.h" +#include "GrBackendSemaphore.h" #include "GrContext.h" #include "GrGpu.h" #include "GrOnFlushResourceProvider.h" @@ -83,11 +84,14 @@ gr_instanced::OpAllocator* GrDrawingManager::instancingAllocator() { } // MDB TODO: make use of the 'proxy' parameter. -void GrDrawingManager::internalFlush(GrSurfaceProxy*, GrResourceCache::FlushType type) { +GrSemaphoresSubmitted GrDrawingManager::internalFlush(GrSurfaceProxy*, + GrResourceCache::FlushType type, + int numSemaphores, + GrBackendSemaphore backendSemaphores[]) { GR_CREATE_TRACE_MARKER_CONTEXT("GrDrawingManager", "internalFlush", fContext); if (fFlushing || this->wasAbandoned()) { - return; + return GrSemaphoresSubmitted::kNo; } fFlushing = true; bool flushed = false; @@ -190,7 +194,8 @@ void GrDrawingManager::internalFlush(GrSurfaceProxy*, GrResourceCache::FlushType SkASSERT(fFlushState.nextDrawToken() == fFlushState.nextTokenToFlush()); - fContext->getGpu()->finishFlush(); + GrSemaphoresSubmitted result = fContext->getGpu()->finishFlush(numSemaphores, + backendSemaphores); fFlushState.reset(); // We always have to notify the cache when it requested a flush so it can reset its state. @@ -201,20 +206,23 @@ void GrDrawingManager::internalFlush(GrSurfaceProxy*, GrResourceCache::FlushType onFlushCBObject->postFlush(); } fFlushing = false; + + return result; } -void GrDrawingManager::prepareSurfaceForExternalIO(GrSurfaceProxy* proxy) { +GrSemaphoresSubmitted GrDrawingManager::prepareSurfaceForExternalIO( + GrSurfaceProxy* proxy, int numSemaphores, GrBackendSemaphore backendSemaphores[]) { if (this->wasAbandoned()) { - return; + return GrSemaphoresSubmitted::kNo; } SkASSERT(proxy); - if (proxy->priv().hasPendingIO()) { - this->flush(proxy); + if (proxy->priv().hasPendingIO() || numSemaphores) { + return this->flush(proxy, numSemaphores, backendSemaphores); } if (!proxy->instantiate(fContext->resourceProvider())) { - return; + return GrSemaphoresSubmitted::kNo; } GrSurface* surface = proxy->priv().peekSurface(); @@ -222,6 +230,7 @@ void GrDrawingManager::prepareSurfaceForExternalIO(GrSurfaceProxy* proxy) { if (fContext->getGpu() && surface->asRenderTarget()) { fContext->getGpu()->resolveRenderTarget(surface->asRenderTarget()); } + return GrSemaphoresSubmitted::kNo; } void GrDrawingManager::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlushCBObject) { diff --git a/src/gpu/GrDrawingManager.h b/src/gpu/GrDrawingManager.h index e7995fd80d..6a1ad19d93 100644 --- a/src/gpu/GrDrawingManager.h +++ b/src/gpu/GrDrawingManager.h @@ -64,13 +64,15 @@ public: void flushIfNecessary() { if (fContext->getResourceCache()->requestsFlush()) { - this->internalFlush(nullptr, GrResourceCache::kCacheRequested); + this->internalFlush(nullptr, GrResourceCache::kCacheRequested, 0, nullptr); } } static bool ProgramUnitTest(GrContext* context, int maxStages, int maxLevels); - void prepareSurfaceForExternalIO(GrSurfaceProxy*); + GrSemaphoresSubmitted prepareSurfaceForExternalIO(GrSurfaceProxy*, + int numSemaphores, + GrBackendSemaphore backendSemaphores[]); void addOnFlushCallbackObject(GrOnFlushCallbackObject*); void testingOnly_removeOnFlushCallbackObject(GrOnFlushCallbackObject*); @@ -93,10 +95,16 @@ private: void abandon(); void cleanup(); void reset(); - void flush(GrSurfaceProxy* proxy) { - this->internalFlush(proxy, GrResourceCache::FlushType::kExternal); + GrSemaphoresSubmitted flush(GrSurfaceProxy* proxy, + int numSemaphores = 0, + GrBackendSemaphore backendSemaphores[] = nullptr) { + return this->internalFlush(proxy, GrResourceCache::FlushType::kExternal, + numSemaphores, backendSemaphores); } - void internalFlush(GrSurfaceProxy*, GrResourceCache::FlushType); + GrSemaphoresSubmitted internalFlush(GrSurfaceProxy*, + GrResourceCache::FlushType, + int numSemaphores, + GrBackendSemaphore backendSemaphores[]); friend class GrContext; // for access to: ctor, abandon, reset & flush friend class GrContextPriv; // access to: flush diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp index afe3956747..2f4b3f784e 100644 --- a/src/gpu/GrGpu.cpp +++ b/src/gpu/GrGpu.cpp @@ -8,6 +8,7 @@ #include "GrGpu.h" +#include "GrBackendSemaphore.h" #include "GrBackendSurface.h" #include "GrBuffer.h" #include "GrCaps.h" @@ -19,6 +20,7 @@ #include "GrRenderTargetPriv.h" #include "GrResourceCache.h" #include "GrResourceProvider.h" +#include "GrSemaphore.h" #include "GrStencilAttachment.h" #include "GrStencilSettings.h" #include "GrSurfacePriv.h" @@ -513,3 +515,26 @@ bool GrGpu::SamplePatternComparator::operator()(const SamplePattern& a, } return false; // Equal. } + +GrSemaphoresSubmitted GrGpu::finishFlush(int numSemaphores, + GrBackendSemaphore backendSemaphores[]) { + if (this->caps()->fenceSyncSupport()) { + for (int i = 0; i < numSemaphores; ++i) { + sk_sp semaphore; + if (backendSemaphores[i].isInitialized()) { + semaphore = fContext->resourceProvider()->wrapBackendSemaphore( + backendSemaphores[i], kBorrow_GrWrapOwnership); + } else { + semaphore = fContext->resourceProvider()->makeSemaphore(false); + } + this->insertSemaphore(semaphore, false); + + if (!backendSemaphores[i].isInitialized()) { + semaphore->setBackendSemaphore(&backendSemaphores[i]); + } + } + } + this->onFinishFlush((numSemaphores > 0 && this->caps()->fenceSyncSupport())); + return this->caps()->fenceSyncSupport() ? GrSemaphoresSubmitted::kYes + : GrSemaphoresSubmitted::kNo; +} diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h index c6684ac4fa..9d8e65a350 100644 --- a/src/gpu/GrGpu.h +++ b/src/gpu/GrGpu.h @@ -41,6 +41,8 @@ class GrStencilSettings; class GrSurface; class GrTexture; +enum class GrSemaphoresSubmitted; + namespace gr_instanced { class InstancedOp; class InstancedRendering; @@ -375,8 +377,10 @@ public: const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) = 0; // Called by GrDrawingManager when flushing. - // Provides a hook for post-flush actions (e.g. Vulkan command buffer submits). - virtual void finishFlush() {} + // Provides a hook for post-flush actions (e.g. Vulkan command buffer submits). This will also + // insert any numSemaphore semaphores on the gpu and set the backendSemaphores to match the + // inserted semaphores. + GrSemaphoresSubmitted finishFlush(int numSemaphores, GrBackendSemaphore backendSemaphores[]); virtual GrFence SK_WARN_UNUSED_RESULT insertFence() = 0; virtual bool waitFence(GrFence, uint64_t timeout = 1000) = 0; @@ -615,6 +619,8 @@ private: virtual void onQueryMultisampleSpecs(GrRenderTarget*, const GrStencilSettings&, int* effectiveSampleCnt, SamplePattern*) = 0; + virtual void onFinishFlush(bool insertedSemaphores) = 0; + void resetContext() { this->onResetContext(fResetBits); fResetBits = 0; diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp index c9898c7480..2247eb3eaa 100644 --- a/src/gpu/GrRenderTargetContext.cpp +++ b/src/gpu/GrRenderTargetContext.cpp @@ -1412,42 +1412,16 @@ void GrRenderTargetContext::drawImageLattice(const GrClip& clip, this->addDrawOp(clip, std::move(op)); } -bool GrRenderTargetContext::prepareForExternalIO(int numSemaphores, - GrBackendSemaphore* backendSemaphores) { +GrSemaphoresSubmitted GrRenderTargetContext::prepareForExternalIO( + int numSemaphores, GrBackendSemaphore backendSemaphores[]) { ASSERT_SINGLE_OWNER - RETURN_FALSE_IF_ABANDONED + if (this->drawingManager()->wasAbandoned()) { return GrSemaphoresSubmitted::kNo; } SkDEBUGCODE(this->validate();) GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "prepareForExternalIO", fContext); - if (numSemaphores && !this->caps()->fenceSyncSupport()) { - this->drawingManager()->prepareSurfaceForExternalIO(fRenderTargetProxy.get()); - return false; - } - - SkTArray> semaphores(numSemaphores); - for (int i = 0; i < numSemaphores; ++i) { - if (backendSemaphores[i].isInitialized()) { - semaphores.push_back(fContext->resourceProvider()->wrapBackendSemaphore( - backendSemaphores[i], kBorrow_GrWrapOwnership)); - } else { - semaphores.push_back(fContext->resourceProvider()->makeSemaphore(false)); - } - // Create signal semaphore ops and force the final one to call flush. - bool forceFlush = (i == (numSemaphores - 1)); - std::unique_ptr signalOp(GrSemaphoreOp::MakeSignal(semaphores.back(), - fRenderTargetProxy.get(), - forceFlush)); - this->getRTOpList()->addOp(std::move(signalOp), *this->caps()); - } - - this->drawingManager()->prepareSurfaceForExternalIO(fRenderTargetProxy.get()); - - for (int i = 0; i < numSemaphores; ++i) { - if (!backendSemaphores[i].isInitialized()) { - semaphores[i]->setBackendSemaphore(&backendSemaphores[i]); - } - } - return true; + return this->drawingManager()->prepareSurfaceForExternalIO(fRenderTargetProxy.get(), + numSemaphores, + backendSemaphores); } bool GrRenderTargetContext::waitOnSemaphores(int numSemaphores, diff --git a/src/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h index 1958ed7c8e..964d9e9a4e 100644 --- a/src/gpu/GrRenderTargetContext.h +++ b/src/gpu/GrRenderTargetContext.h @@ -303,7 +303,8 @@ public: * After this returns any pending surface IO will be issued to the backend 3D API and * if the surface has MSAA it will be resolved. */ - bool prepareForExternalIO(int numSemaphores, GrBackendSemaphore* backendSemaphores); + GrSemaphoresSubmitted prepareForExternalIO(int numSemaphores, + GrBackendSemaphore backendSemaphores[]); /** * The next time this GrRenderTargetContext is flushed, the gpu will wait on the passed in diff --git a/src/gpu/GrSemaphore.h b/src/gpu/GrSemaphore.h index f6148b015a..fbc5a6df56 100644 --- a/src/gpu/GrSemaphore.h +++ b/src/gpu/GrSemaphore.h @@ -29,6 +29,7 @@ private: protected: explicit GrSemaphore(const GrGpu* gpu) : fGpu(gpu) {} + friend class GrGpu; // setBackendSemaphore friend class GrRenderTargetContext; // setBackendSemaphore friend class GrResourceProvider; // resetGpu diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index 57b2d41def..607165cfd3 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -1734,8 +1734,8 @@ void SkGpuDevice::flush() { this->flushAndSignalSemaphores(0, nullptr); } -bool SkGpuDevice::flushAndSignalSemaphores(int numSemaphores, - GrBackendSemaphore* signalSemaphores) { +GrSemaphoresSubmitted SkGpuDevice::flushAndSignalSemaphores(int numSemaphores, + GrBackendSemaphore signalSemaphores[]) { ASSERT_SINGLE_OWNER return fRenderTargetContext->prepareForExternalIO(numSemaphores, signalSemaphores); diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h index 3fc3807d22..f1bd937269 100644 --- a/src/gpu/SkGpuDevice.h +++ b/src/gpu/SkGpuDevice.h @@ -118,7 +118,8 @@ public: sk_sp snapSpecial() override; void flush() override; - bool flushAndSignalSemaphores(int numSemaphores, GrBackendSemaphore* signalSemaphores); + GrSemaphoresSubmitted flushAndSignalSemaphores(int numSemaphores, + GrBackendSemaphore signalSemaphores[]); bool wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores); bool onAccessPixels(SkPixmap*) override; diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index 49be761350..209cd41be9 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -4352,6 +4352,13 @@ bool GrGLGpu::onIsACopyNeededForTextureParams(GrTextureProxy* proxy, return false; } +void GrGLGpu::onFinishFlush(bool insertedSemaphore) { + // If we inserted semaphores during the flush, we need to call GLFlush. + if (insertedSemaphore) { + GL_CALL(Flush()); + } +} + GrFence SK_WARN_UNUSED_RESULT GrGLGpu::insertFence() { SkASSERT(this->caps()->fenceSyncSupport()); GrGLsync sync; @@ -4381,7 +4388,6 @@ sk_sp GrGLGpu::wrapBackendSemaphore(const GrBackendSemaphore& semap return GrGLSemaphore::MakeWrapped(this, semaphore.glSync(), ownership); } - void GrGLGpu::insertSemaphore(sk_sp semaphore, bool flush) { GrGLSemaphore* glSem = static_cast(semaphore.get()); diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h index 9b6e004bd5..b1d19be042 100644 --- a/src/gpu/gl/GrGLGpu.h +++ b/src/gpu/gl/GrGLGpu.h @@ -284,6 +284,8 @@ private: void flushBlend(const GrXferProcessor::BlendInfo& blendInfo, const GrSwizzle&); + void onFinishFlush(bool insertedSemaphores) override; + bool hasExtension(const char* ext) const { return fGLContext->hasExtension(ext); } bool copySurfaceAsDraw(GrSurface* dst, diff --git a/src/gpu/mock/GrMockGpu.h b/src/gpu/mock/GrMockGpu.h index e31570ad07..5745a685ae 100644 --- a/src/gpu/mock/GrMockGpu.h +++ b/src/gpu/mock/GrMockGpu.h @@ -122,6 +122,8 @@ private: void onResolveRenderTarget(GrRenderTarget* target) override { return; } + void onFinishFlush(bool insertedSemaphores) override {} + GrStencilAttachment* createStencilAttachmentForRenderTarget(const GrRenderTarget*, int width, int height) override; diff --git a/src/gpu/mtl/GrMtlGpu.h b/src/gpu/mtl/GrMtlGpu.h index f150e3034a..edb3059655 100644 --- a/src/gpu/mtl/GrMtlGpu.h +++ b/src/gpu/mtl/GrMtlGpu.h @@ -126,6 +126,8 @@ private: void onResolveRenderTarget(GrRenderTarget* target) override { return; } + void onFinishFlush(bool insertedSemaphores) override {} + GrStencilAttachment* createStencilAttachmentForRenderTarget(const GrRenderTarget*, int width, int height) override { diff --git a/src/gpu/vk/GrVkCopyManager.cpp b/src/gpu/vk/GrVkCopyManager.cpp index f0dc60297b..3851bc650a 100644 --- a/src/gpu/vk/GrVkCopyManager.cpp +++ b/src/gpu/vk/GrVkCopyManager.cpp @@ -160,7 +160,7 @@ bool GrVkCopyManager::copySurfaceAsDraw(GrVkGpu* gpu, if (gpu->vkCaps().newCBOnPipelineChange()) { // We bind a new pipeline here for the copy so we must start a new command buffer. - gpu->finishFlush(); + gpu->finishFlush(0, nullptr); } GrVkRenderTarget* rt = static_cast(dst->asRenderTarget()); diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp index d7094b7c18..5979ae0f49 100644 --- a/src/gpu/vk/GrVkGpu.cpp +++ b/src/gpu/vk/GrVkGpu.cpp @@ -1467,8 +1467,9 @@ void GrVkGpu::addImageMemoryBarrier(VkPipelineStageFlags srcStageMask, barrier); } -void GrVkGpu::finishFlush() { - // Submit the current command buffer to the Queue +void GrVkGpu::onFinishFlush(bool insertedSemaphore) { + // Submit the current command buffer to the Queue. Whether we inserted semaphores or not does + // not effect what we do here. this->submitCommandBuffer(kSkip_SyncQueue); } diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h index 419e9e3ad6..d81c2e6c22 100644 --- a/src/gpu/vk/GrVkGpu.h +++ b/src/gpu/vk/GrVkGpu.h @@ -125,8 +125,6 @@ public: GrVkRenderTarget*, const SkIRect& bounds); - void finishFlush() override; - GrFence SK_WARN_UNUSED_RESULT insertFence() override; bool waitFence(GrFence, uint64_t timeout) override; void deleteFence(GrFence) const override; @@ -210,6 +208,8 @@ private: GrPixelConfig config, GrBuffer* transferBuffer, size_t offset, size_t rowBytes) override; + void onFinishFlush(bool insertedSemaphores) override; + // Ends and submits the current command buffer to the queue and then creates a new command // buffer and begins it. If sync is set to kForce_SyncQueue, the function will wait for all // work in the queue to finish before returning. If this GrVkGpu object has any semaphores in diff --git a/src/image/SkSurface.cpp b/src/image/SkSurface.cpp index 29068b2c4a..ead0062aa8 100644 --- a/src/image/SkSurface.cpp +++ b/src/image/SkSurface.cpp @@ -200,7 +200,8 @@ void SkSurface::flush() { asSB(this)->onFlush(0, nullptr); } -bool SkSurface::flushAndSignalSemaphores(int numSemaphores, GrBackendSemaphore* signalSemaphores) { +GrSemaphoresSubmitted SkSurface::flushAndSignalSemaphores(int numSemaphores, + GrBackendSemaphore signalSemaphores[]) { return asSB(this)->onFlush(numSemaphores, signalSemaphores); } diff --git a/src/image/SkSurface_Base.h b/src/image/SkSurface_Base.h index 93528b8d5d..c847b09aab 100644 --- a/src/image/SkSurface_Base.h +++ b/src/image/SkSurface_Base.h @@ -80,8 +80,9 @@ public: * Inserts the requested number of semaphores for the gpu to signal when work is complete on the * gpu and inits the array of GrBackendSemaphores with the signaled semaphores. */ - virtual bool onFlush(int numSemaphores, GrBackendSemaphore* signalSemaphores) { - return false; + virtual GrSemaphoresSubmitted onFlush(int numSemaphores, + GrBackendSemaphore signalSemaphores[]) { + return (GrSemaphoresSubmitted)0; } /** diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp index 143a6039f0..7f65a3e2f2 100644 --- a/src/image/SkSurface_Gpu.cpp +++ b/src/image/SkSurface_Gpu.cpp @@ -148,7 +148,8 @@ void SkSurface_Gpu::onDiscard() { fDevice->accessRenderTargetContext()->discard(); } -bool SkSurface_Gpu::onFlush(int numSemaphores, GrBackendSemaphore* signalSemaphores) { +GrSemaphoresSubmitted SkSurface_Gpu::onFlush(int numSemaphores, + GrBackendSemaphore signalSemaphores[]) { return fDevice->flushAndSignalSemaphores(numSemaphores, signalSemaphores); } diff --git a/src/image/SkSurface_Gpu.h b/src/image/SkSurface_Gpu.h index 2bc9210b34..ebf7d4ed44 100644 --- a/src/image/SkSurface_Gpu.h +++ b/src/image/SkSurface_Gpu.h @@ -26,7 +26,8 @@ public: sk_sp onNewImageSnapshot() override; void onCopyOnWrite(ContentChangeMode) override; void onDiscard() override; - bool onFlush(int numSemaphores, GrBackendSemaphore* signalSemaphores) override; + GrSemaphoresSubmitted onFlush(int numSemaphores, + GrBackendSemaphore signalSemaphores[]) override; bool onWait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) override; SkGpuDevice* getDevice() { return fDevice.get(); } diff --git a/tests/SurfaceSemaphoreTest.cpp b/tests/SurfaceSemaphoreTest.cpp index cd3b8e587b..bb726c2eec 100644 --- a/tests/SurfaceSemaphoreTest.cpp +++ b/tests/SurfaceSemaphoreTest.cpp @@ -108,7 +108,8 @@ void draw_child(skiatest::Reporter* reporter, void surface_semaphore_test(skiatest::Reporter* reporter, const sk_gpu_test::ContextInfo& mainInfo, const sk_gpu_test::ContextInfo& childInfo1, - const sk_gpu_test::ContextInfo& childInfo2) { + const sk_gpu_test::ContextInfo& childInfo2, + bool flushContext) { GrContext* mainCtx = mainInfo.grContext(); if (!mainCtx->caps()->fenceSyncSupport()) { return; @@ -143,7 +144,11 @@ void surface_semaphore_test(skiatest::Reporter* reporter, } #endif - mainSurface->flushAndSignalSemaphores(2, semaphores.get()); + if (flushContext) { + mainCtx->flushAndSignalSemaphores(2, semaphores.get()); + } else { + mainSurface->flushAndSignalSemaphores(2, semaphores.get()); + } sk_sp mainImage = mainSurface->makeImageSnapshot(); GrBackendObject backendImage = mainImage->getTextureHandle(false); @@ -171,31 +176,35 @@ DEF_GPUTEST(SurfaceSemaphores, reporter, factory) { #endif for (int typeInt = 0; typeInt < sk_gpu_test::GrContextFactory::kContextTypeCnt; ++typeInt) { - sk_gpu_test::GrContextFactory::ContextType contextType = - (sk_gpu_test::GrContextFactory::ContextType) typeInt; - // Use "native" instead of explicitly trying OpenGL and OpenGL ES. Do not use GLES on - // desktop since tests do not account for not fixing http://skbug.com/2809 - if (contextType == sk_gpu_test::GrContextFactory::kGL_ContextType || - contextType == sk_gpu_test::GrContextFactory::kGLES_ContextType) { - if (contextType != kNativeGLType) { - continue; + for (auto flushContext : { false, true }) { + sk_gpu_test::GrContextFactory::ContextType contextType = + (sk_gpu_test::GrContextFactory::ContextType) typeInt; + // Use "native" instead of explicitly trying OpenGL and OpenGL ES. Do not use GLES on + // desktop since tests do not account for not fixing http://skbug.com/2809 + if (contextType == sk_gpu_test::GrContextFactory::kGL_ContextType || + contextType == sk_gpu_test::GrContextFactory::kGLES_ContextType) { + if (contextType != kNativeGLType) { + continue; + } } - } - sk_gpu_test::ContextInfo ctxInfo = factory->getContextInfo( - contextType, sk_gpu_test::GrContextFactory::ContextOverrides::kDisableNVPR); - if (!sk_gpu_test::GrContextFactory::IsRenderingContext(contextType)) { - continue; - } - skiatest::ReporterContext ctx( - reporter, SkString(sk_gpu_test::GrContextFactory::ContextTypeName(contextType))); - if (ctxInfo.grContext()) { - sk_gpu_test::ContextInfo child1 = factory->getSharedContextInfo(ctxInfo.grContext(), 0); - sk_gpu_test::ContextInfo child2 = factory->getSharedContextInfo(ctxInfo.grContext(), 1); - if (!child1.grContext() || !child2.grContext()) { + sk_gpu_test::ContextInfo ctxInfo = factory->getContextInfo( + contextType, sk_gpu_test::GrContextFactory::ContextOverrides::kDisableNVPR); + if (!sk_gpu_test::GrContextFactory::IsRenderingContext(contextType)) { continue; } + skiatest::ReporterContext ctx( + reporter, SkString(sk_gpu_test::GrContextFactory::ContextTypeName(contextType))); + if (ctxInfo.grContext()) { + sk_gpu_test::ContextInfo child1 = factory->getSharedContextInfo(ctxInfo.grContext(), + 0); + sk_gpu_test::ContextInfo child2 = factory->getSharedContextInfo(ctxInfo.grContext(), + 1); + if (!child1.grContext() || !child2.grContext()) { + continue; + } - surface_semaphore_test(reporter, ctxInfo, child1, child2); + surface_semaphore_test(reporter, ctxInfo, child1, child2, flushContext); + } } } } @@ -217,7 +226,8 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(EmptySurfaceSemaphoreTest, reporter, ctxInfo) mainSurface->flush(); GrBackendSemaphore semaphore; - REPORTER_ASSERT(reporter, mainSurface->flushAndSignalSemaphores(1, &semaphore)); + GrSemaphoresSubmitted submitted = mainSurface->flushAndSignalSemaphores(1, &semaphore); + REPORTER_ASSERT(reporter, GrSemaphoresSubmitted::kYes == submitted); if (kOpenGL_GrBackend == ctxInfo.backend()) { GrGLGpu* gpu = static_cast(ctx->getGpu()); -- cgit v1.2.3