aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Greg Daniel <egdaniel@google.com>2018-01-22 16:11:35 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-01-22 21:41:45 +0000
commit48661b868fbbf7a6193ef49bb6a05a0df61e7c45 (patch)
tree13582c20667d91e8989f76c224d99f2231714730
parent2e6feed858c2b14b9083cf7d2b040a177dcb62ea (diff)
Make use of VkSemaphores thread safe assuming use of the same VkQueue.
This allows us to re-enable support for multiple GrContexts in GrBackendTextureImageGenerator. Bug: skia: Change-Id: Ifd6ac1ad81cdfbd1fd986467d8beb359399d6588 Reviewed-on: https://skia-review.googlesource.com/98340 Reviewed-by: Brian Osman <brianosman@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Greg Daniel <egdaniel@google.com>
-rw-r--r--include/core/SkImage.h4
-rw-r--r--src/gpu/GrBackendTextureImageGenerator.cpp5
-rw-r--r--src/gpu/GrGpu.cpp46
-rw-r--r--src/gpu/GrGpu.h15
-rw-r--r--src/gpu/GrSemaphore.h11
-rw-r--r--src/gpu/ddl/GrDDLGpu.h24
-rw-r--r--src/gpu/gl/GrGLGpu.cpp18
-rw-r--r--src/gpu/gl/GrGLGpu.h10
-rw-r--r--src/gpu/mock/GrMockGpu.h10
-rw-r--r--src/gpu/mtl/GrMtlGpu.h10
-rw-r--r--src/gpu/vk/GrVkCommandBuffer.cpp96
-rw-r--r--src/gpu/vk/GrVkCommandBuffer.h4
-rw-r--r--src/gpu/vk/GrVkGpu.cpp24
-rw-r--r--src/gpu/vk/GrVkGpu.h15
-rw-r--r--src/gpu/vk/GrVkSemaphore.cpp14
-rw-r--r--src/gpu/vk/GrVkSemaphore.h42
-rw-r--r--tests/ImageTest.cpp5
17 files changed, 187 insertions, 166 deletions
diff --git a/include/core/SkImage.h b/include/core/SkImage.h
index 9ebddc5c45..74d5b90652 100644
--- a/include/core/SkImage.h
+++ b/include/core/SkImage.h
@@ -171,7 +171,7 @@ public:
* Decodes and uploads the encoded data to a GPU backed image using the supplied GrContext.
* That image can be safely used by other GrContexts, across thread boundaries. The GrContext
* used here, and the ones used to draw this image later must be in the same GL share group,
- * or otherwise be able to share resources.
+ * or use the same Vulkan VkDevice and VkQueue, or otherwise be able to share resources.
*
* When the image's ref count reaches zero, the original GrContext will destroy the texture,
* asynchronously.
@@ -187,7 +187,7 @@ public:
* Uploads the pixmap to a GPU backed image using the supplied GrContext.
* That image can be safely used by other GrContexts, across thread boundaries. The GrContext
* used here, and the ones used to draw this image later must be in the same GL share group,
- * or otherwise be able to share resources.
+ * or use the same Vulkan VkDevice and VkQueue, or otherwise be able to share resources.
*
* When the image's ref count reaches zero, the original GrContext will destroy the texture,
* asynchronously.
diff --git a/src/gpu/GrBackendTextureImageGenerator.cpp b/src/gpu/GrBackendTextureImageGenerator.cpp
index 9b55704dce..b07115ef2d 100644
--- a/src/gpu/GrBackendTextureImageGenerator.cpp
+++ b/src/gpu/GrBackendTextureImageGenerator.cpp
@@ -80,6 +80,7 @@ void GrBackendTextureImageGenerator::ReleaseRefHelper_TextureReleaseProc(void* c
SkASSERT(refHelper);
refHelper->fBorrowedTexture = nullptr;
+ refHelper->fBorrowingContextID = SK_InvalidGenID;
refHelper->unref();
}
@@ -125,11 +126,12 @@ sk_sp<GrTextureProxy> GrBackendTextureImageGenerator::onGenerateTexture(
if (!resourceProvider) {
// If we get here then we never created a texture to pass the refHelper ref off
// to. Thus we must unref it ourselves.
+ refHelper->fBorrowingContextID = SK_InvalidGenID;
refHelper->unref();
return sk_sp<GrTexture>();
}
- if (semaphore && !semaphore->hasSubmittedWait()) {
+ if (semaphore) {
resourceProvider->priv().gpu()->waitSemaphore(semaphore);
}
@@ -155,6 +157,7 @@ sk_sp<GrTextureProxy> GrBackendTextureImageGenerator::onGenerateTexture(
tex = resourceProvider->wrapBackendTexture(backendTexture,
kBorrow_GrWrapOwnership);
if (!tex) {
+ refHelper->fBorrowingContextID = SK_InvalidGenID;
refHelper->unref();
return sk_sp<GrTexture>();
}
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index 93f719ab48..eb005d110a 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -517,49 +517,3 @@ void GrGpu::dumpJSON(SkJSONWriter* writer) const {
writer->endObject();
}
-
-void GrGpu::insertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush) {
- if (!semaphore) {
- return;
- }
-
- SkASSERT(!semaphore->fSignaled);
- if (semaphore->fSignaled) {
- this->onInsertSemaphore(nullptr, flush);
- return;
- }
- this->onInsertSemaphore(semaphore, flush);
- semaphore->fSignaled = true;
-}
-
-void GrGpu::waitSemaphore(sk_sp<GrSemaphore> semaphore) {
- if (!semaphore) {
- return;
- }
-
- SkASSERT(!semaphore->fWaitedOn);
- if (!semaphore->fWaitedOn) {
- this->onWaitSemaphore(semaphore);
- semaphore->fWaitedOn = true;
- }
-}
-
-sk_sp<GrSemaphore> GrGpu::wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
- GrResourceProvider::SemaphoreWrapType wrapType,
- GrWrapOwnership ownership) {
- sk_sp<GrSemaphore> grSema = this->onWrapBackendSemaphore(semaphore, ownership);
- if (GrResourceProvider::SemaphoreWrapType::kWillSignal == wrapType) {
- // This is a safety check to make sure we never try to wait on this semaphore since we
- // assume the client will wait on it themselves if they've asked us to signal it.
- grSema->fWaitedOn = true;
- } else {
- SkASSERT(GrResourceProvider::SemaphoreWrapType::kWillWait == wrapType);
- // This is a safety check to make sure we never try to signal this semaphore since we assume
- // the client will signal it themselves if they've asked us wait on it.
- grSema->fSignaled = true;
- }
-
- SkASSERT(this->caps()->fenceSyncSupport());
- return grSema;
-}
-
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index e8e0ab9141..2f12073f8a 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -377,11 +377,11 @@ public:
virtual void deleteFence(GrFence) const = 0;
virtual sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT makeSemaphore(bool isOwned = true) = 0;
- sk_sp<GrSemaphore> wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
- GrResourceProvider::SemaphoreWrapType wrapType,
- GrWrapOwnership ownership);
- void insertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush = false);
- void waitSemaphore(sk_sp<GrSemaphore> semaphore);
+ virtual sk_sp<GrSemaphore> wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
+ GrResourceProvider::SemaphoreWrapType wrapType,
+ GrWrapOwnership ownership) = 0;
+ virtual void insertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush = false) = 0;
+ virtual void waitSemaphore(sk_sp<GrSemaphore> semaphore) = 0;
/**
* Put this texture in a safe and known state for use across multiple GrContexts. Depending on
@@ -606,11 +606,6 @@ private:
virtual void onFinishFlush(bool insertedSemaphores) = 0;
- virtual void onInsertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush = false) = 0;
- virtual void onWaitSemaphore(sk_sp<GrSemaphore> semaphore) = 0;
- virtual sk_sp<GrSemaphore> onWrapBackendSemaphore(const GrBackendSemaphore& semaphore,
- GrWrapOwnership ownership) = 0;
-
virtual void onDumpJSON(SkJSONWriter*) const {}
void resetContext() {
diff --git a/src/gpu/GrSemaphore.h b/src/gpu/GrSemaphore.h
index 20556d27ac..fbc5a6df56 100644
--- a/src/gpu/GrSemaphore.h
+++ b/src/gpu/GrSemaphore.h
@@ -13,15 +13,7 @@
class GrBackendSemaphore;
class GrGpu;
-/*
- * Wrapper around a semaphore object which must be implemented on each backend. This semaphores can
- * at most be signaled once and waited upon once.
- */
class GrSemaphore : public SkRefCnt {
-public:
- bool hasSubmittedSignal() const { return fSignaled; }
- bool hasSubmittedWait() const { return fWaitedOn; }
-
private:
// This function should only be used in the case of exporting and importing a GrSemaphore object
// from one GrContext to another. When exporting, the GrSemaphore should be set to a null GrGpu,
@@ -34,9 +26,6 @@ private:
// internal semaphore.
virtual void setBackendSemaphore(GrBackendSemaphore*) const = 0;
- bool fSignaled = false;
- bool fWaitedOn = false;
-
protected:
explicit GrSemaphore(const GrGpu* gpu) : fGpu(gpu) {}
diff --git a/src/gpu/ddl/GrDDLGpu.h b/src/gpu/ddl/GrDDLGpu.h
index e97a2abf4a..16deab0353 100644
--- a/src/gpu/ddl/GrDDLGpu.h
+++ b/src/gpu/ddl/GrDDLGpu.h
@@ -72,6 +72,18 @@ public:
SkASSERT(0);
return nullptr;
}
+ sk_sp<GrSemaphore> wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
+ GrResourceProvider::SemaphoreWrapType wrapType,
+ GrWrapOwnership ownership) override {
+ SkASSERT(0);
+ return nullptr;
+ }
+ void insertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush) override {
+ SkASSERT(0);
+ }
+ void waitSemaphore(sk_sp<GrSemaphore> semaphore) override {
+ SkASSERT(0);
+ }
sk_sp<GrSemaphore> prepareTextureForCrossContextUsage(GrTexture*) override {
SkASSERT(0);
return nullptr;
@@ -147,18 +159,6 @@ private:
void onFinishFlush(bool insertedSemaphores) override { SkASSERT(0); }
- sk_sp<GrSemaphore> onWrapBackendSemaphore(const GrBackendSemaphore& semaphore,
- GrWrapOwnership ownership) override {
- SkASSERT(0);
- return nullptr;
- }
- void onInsertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush) override {
- SkASSERT(0);
- }
- void onWaitSemaphore(sk_sp<GrSemaphore> semaphore) override {
- SkASSERT(0);
- }
-
GrStencilAttachment* createStencilAttachmentForRenderTarget(const GrRenderTarget*,
int width,
int height) override;
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 267b405b67..212826d0dd 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -4579,29 +4579,27 @@ sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT GrGLGpu::makeSemaphore(bool isOwned) {
return GrGLSemaphore::Make(this, isOwned);
}
-sk_sp<GrSemaphore> GrGLGpu::onWrapBackendSemaphore(const GrBackendSemaphore& semaphore,
- GrWrapOwnership ownership) {
+sk_sp<GrSemaphore> GrGLGpu::wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
+ GrResourceProvider::SemaphoreWrapType wrapType,
+ GrWrapOwnership ownership) {
SkASSERT(this->caps()->fenceSyncSupport());
return GrGLSemaphore::MakeWrapped(this, semaphore.glSync(), ownership);
}
-void GrGLGpu::onInsertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush) {
+void GrGLGpu::insertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush) {
GrGLSemaphore* glSem = static_cast<GrGLSemaphore*>(semaphore.get());
- if (glSem) {
- GrGLsync sync;
- GL_CALL_RET(sync, FenceSync(GR_GL_SYNC_GPU_COMMANDS_COMPLETE, 0));
- glSem->setSync(sync);
- }
+ GrGLsync sync;
+ GL_CALL_RET(sync, FenceSync(GR_GL_SYNC_GPU_COMMANDS_COMPLETE, 0));
+ glSem->setSync(sync);
if (flush) {
GL_CALL(Flush());
}
}
-void GrGLGpu::onWaitSemaphore(sk_sp<GrSemaphore> semaphore) {
+void GrGLGpu::waitSemaphore(sk_sp<GrSemaphore> semaphore) {
GrGLSemaphore* glSem = static_cast<GrGLSemaphore*>(semaphore.get());
- SkASSERT(glSem);
GL_CALL(WaitSync(glSem->sync(), 0, GR_GL_TIMEOUT_IGNORED));
}
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 2087356f04..9ac86ba123 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -173,6 +173,11 @@ public:
void deleteFence(GrFence) const override;
sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT makeSemaphore(bool isOwned) override;
+ sk_sp<GrSemaphore> wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
+ GrResourceProvider::SemaphoreWrapType wrapType,
+ GrWrapOwnership ownership) override;
+ void insertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush) override;
+ void waitSemaphore(sk_sp<GrSemaphore> semaphore) override;
sk_sp<GrSemaphore> prepareTextureForCrossContextUsage(GrTexture*) override;
@@ -286,11 +291,6 @@ private:
void onFinishFlush(bool insertedSemaphores) override;
- void onInsertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush) override;
- void onWaitSemaphore(sk_sp<GrSemaphore> semaphore) override;
- sk_sp<GrSemaphore> onWrapBackendSemaphore(const GrBackendSemaphore& semaphore,
- GrWrapOwnership ownership) override;
-
bool hasExtension(const char* ext) const { return fGLContext->hasExtension(ext); }
bool copySurfaceAsDraw(GrSurface* dst, GrSurfaceOrigin dstOrigin,
diff --git a/src/gpu/mock/GrMockGpu.h b/src/gpu/mock/GrMockGpu.h
index 359782f0c9..5185ce28f0 100644
--- a/src/gpu/mock/GrMockGpu.h
+++ b/src/gpu/mock/GrMockGpu.h
@@ -58,6 +58,11 @@ public:
sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT makeSemaphore(bool isOwned) override {
return nullptr;
}
+ sk_sp<GrSemaphore> wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
+ GrResourceProvider::SemaphoreWrapType wrapType,
+ GrWrapOwnership ownership) override { return nullptr; }
+ void insertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush) override {}
+ void waitSemaphore(sk_sp<GrSemaphore> semaphore) override {}
sk_sp<GrSemaphore> prepareTextureForCrossContextUsage(GrTexture*) override { return nullptr; }
void submitCommandBuffer(const GrMockGpuRTCommandBuffer*);
@@ -120,11 +125,6 @@ private:
void onFinishFlush(bool insertedSemaphores) override {}
- sk_sp<GrSemaphore> onWrapBackendSemaphore(const GrBackendSemaphore& semaphore,
- GrWrapOwnership ownership) override { return nullptr; }
- void onInsertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush) override {}
- void onWaitSemaphore(sk_sp<GrSemaphore> semaphore) 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 61cbc62f71..5a5289b6e1 100644
--- a/src/gpu/mtl/GrMtlGpu.h
+++ b/src/gpu/mtl/GrMtlGpu.h
@@ -67,6 +67,11 @@ public:
sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT makeSemaphore(bool isOwned) override {
return nullptr;
}
+ sk_sp<GrSemaphore> wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
+ GrResourceProvider::SemaphoreWrapType wrapType,
+ GrWrapOwnership ownership) override { return nullptr; }
+ void insertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush) override {}
+ void waitSemaphore(sk_sp<GrSemaphore> semaphore) override {}
sk_sp<GrSemaphore> prepareTextureForCrossContextUsage(GrTexture*) override { return nullptr; }
private:
@@ -129,11 +134,6 @@ private:
void onFinishFlush(bool insertedSemaphores) override {}
- sk_sp<GrSemaphore> onWrapBackendSemaphore(const GrBackendSemaphore& semaphore,
- GrWrapOwnership ownership) override { return nullptr; }
- void onInsertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush) override {}
- void onWaitSemaphore(sk_sp<GrSemaphore> semaphore) override {}
-
GrStencilAttachment* createStencilAttachmentForRenderTarget(const GrRenderTarget*,
int width,
int height) override {
diff --git a/src/gpu/vk/GrVkCommandBuffer.cpp b/src/gpu/vk/GrVkCommandBuffer.cpp
index 8a17a4f033..27642dfe63 100644
--- a/src/gpu/vk/GrVkCommandBuffer.cpp
+++ b/src/gpu/vk/GrVkCommandBuffer.cpp
@@ -445,12 +445,36 @@ void GrVkPrimaryCommandBuffer::executeCommands(const GrVkGpu* gpu,
this->invalidateState();
}
+static void submit_to_queue(const GrVkInterface* interface,
+ VkQueue queue,
+ VkFence fence,
+ uint32_t waitCount,
+ const VkSemaphore* waitSemaphores,
+ const VkPipelineStageFlags* waitStages,
+ uint32_t commandBufferCount,
+ const VkCommandBuffer* commandBuffers,
+ uint32_t signalCount,
+ const VkSemaphore* signalSemaphores) {
+ VkSubmitInfo submitInfo;
+ memset(&submitInfo, 0, sizeof(VkSubmitInfo));
+ submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submitInfo.pNext = nullptr;
+ submitInfo.waitSemaphoreCount = waitCount;
+ submitInfo.pWaitSemaphores = waitSemaphores;
+ submitInfo.pWaitDstStageMask = waitStages;
+ submitInfo.commandBufferCount = commandBufferCount;
+ submitInfo.pCommandBuffers = commandBuffers;
+ submitInfo.signalSemaphoreCount = signalCount;
+ submitInfo.pSignalSemaphores = signalSemaphores;
+ GR_VK_CALL_ERRCHECK(interface, QueueSubmit(queue, 1, &submitInfo, fence));
+}
+
void GrVkPrimaryCommandBuffer::submitToQueue(
const GrVkGpu* gpu,
VkQueue queue,
GrVkGpu::SyncQueue sync,
- SkTArray<const GrVkSemaphore::Resource*>& signalSemaphores,
- SkTArray<const GrVkSemaphore::Resource*>& waitSemaphores) {
+ SkTArray<GrVkSemaphore::Resource*>& signalSemaphores,
+ SkTArray<GrVkSemaphore::Resource*>& waitSemaphores) {
SkASSERT(!fIsActive);
VkResult err;
@@ -466,33 +490,51 @@ void GrVkPrimaryCommandBuffer::submitToQueue(
}
int signalCount = signalSemaphores.count();
- SkTArray<VkSemaphore> vkSignalSem(signalCount);
- for (int i = 0; i < signalCount; ++i) {
- this->addResource(signalSemaphores[i]);
- vkSignalSem.push_back(signalSemaphores[i]->semaphore());
- }
-
int waitCount = waitSemaphores.count();
- SkTArray<VkSemaphore> vkWaitSems(waitCount);
- SkTArray<VkPipelineStageFlags> vkWaitStages(waitCount);
- for (int i = 0; i < waitCount; ++i) {
- this->addResource(waitSemaphores[i]);
- vkWaitSems.push_back(waitSemaphores[i]->semaphore());
- vkWaitStages.push_back(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 = waitCount;
- submitInfo.pWaitSemaphores = vkWaitSems.begin();
- submitInfo.pWaitDstStageMask = vkWaitStages.begin();
- submitInfo.commandBufferCount = 1;
- submitInfo.pCommandBuffers = &fCmdBuffer;
- submitInfo.signalSemaphoreCount = vkSignalSem.count();
- submitInfo.pSignalSemaphores = vkSignalSem.begin();
- GR_VK_CALL_ERRCHECK(gpu->vkInterface(), QueueSubmit(queue, 1, &submitInfo, fSubmitFence));
+ if (0 == signalCount && 0 == waitCount) {
+ // This command buffer has no dependent semaphores so we can simply just submit it to the
+ // queue with no worries.
+ submit_to_queue(gpu->vkInterface(), queue, fSubmitFence, 0, nullptr, nullptr,
+ 1, &fCmdBuffer, 0, nullptr);
+ } else {
+ GrVkSemaphore::Resource::AcquireMutex();
+
+ SkTArray<VkSemaphore> vkSignalSems(signalCount);
+ for (int i = 0; i < signalCount; ++i) {
+ if (signalSemaphores[i]->shouldSignal()) {
+ this->addResource(signalSemaphores[i]);
+ vkSignalSems.push_back(signalSemaphores[i]->semaphore());
+ }
+ }
+
+ SkTArray<VkSemaphore> vkWaitSems(waitCount);
+ SkTArray<VkPipelineStageFlags> vkWaitStages(waitCount);
+ for (int i = 0; i < waitCount; ++i) {
+ if (waitSemaphores[i]->shouldWait()) {
+ this->addResource(waitSemaphores[i]);
+ vkWaitSems.push_back(waitSemaphores[i]->semaphore());
+ vkWaitStages.push_back(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
+ }
+ }
+ submit_to_queue(gpu->vkInterface(), queue, fSubmitFence,
+ vkWaitSems.count(), vkWaitSems.begin(), vkWaitStages.begin(),
+ 1, &fCmdBuffer,
+ vkSignalSems.count(), vkSignalSems.begin());
+ // Since shouldSignal/Wait do not require a mutex to be held, we must make sure that we mark
+ // the semaphores after we've submitted. Thus in the worst case another submit grabs the
+ // mutex and then realizes it doesn't need to submit the semaphore. We will never end up
+ // where a semaphore doesn't think it needs to be submitted (cause of querying
+ // shouldSignal/Wait), but it should need to.
+ for (int i = 0; i < signalCount; ++i) {
+ signalSemaphores[i]->markAsSignaled();
+ }
+ for (int i = 0; i < waitCount; ++i) {
+ waitSemaphores[i]->markAsWaited();
+ }
+
+ GrVkSemaphore::Resource::ReleaseMutex();
+ }
if (GrVkGpu::kForce_SyncQueue == sync) {
err = GR_VK_CALL(gpu->vkInterface(),
diff --git a/src/gpu/vk/GrVkCommandBuffer.h b/src/gpu/vk/GrVkCommandBuffer.h
index 7d16242e6b..362d457773 100644
--- a/src/gpu/vk/GrVkCommandBuffer.h
+++ b/src/gpu/vk/GrVkCommandBuffer.h
@@ -269,8 +269,8 @@ public:
const VkImageResolve* regions);
void submitToQueue(const GrVkGpu* gpu, VkQueue queue, GrVkGpu::SyncQueue sync,
- SkTArray<const GrVkSemaphore::Resource*>& signalSemaphores,
- SkTArray<const GrVkSemaphore::Resource*>& waitSemaphores);
+ SkTArray<GrVkSemaphore::Resource*>& signalSemaphores,
+ SkTArray<GrVkSemaphore::Resource*>& waitSemaphores);
bool finished(const GrVkGpu* gpu) const;
#ifdef SK_TRACE_VK_RESOURCES
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index e1be99e872..f7e3d47dd9 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -2162,16 +2162,17 @@ sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT GrVkGpu::makeSemaphore(bool isOwned) {
return GrVkSemaphore::Make(this, isOwned);
}
-sk_sp<GrSemaphore> GrVkGpu::onWrapBackendSemaphore(const GrBackendSemaphore& semaphore,
- GrWrapOwnership ownership) {
- return GrVkSemaphore::MakeWrapped(this, semaphore.vkSemaphore(), ownership);
+sk_sp<GrSemaphore> GrVkGpu::wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
+ GrResourceProvider::SemaphoreWrapType wrapType,
+ GrWrapOwnership ownership) {
+ return GrVkSemaphore::MakeWrapped(this, semaphore.vkSemaphore(), wrapType, ownership);
}
-void GrVkGpu::onInsertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush) {
+void GrVkGpu::insertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush) {
GrVkSemaphore* vkSem = static_cast<GrVkSemaphore*>(semaphore.get());
- if (vkSem) {
- const GrVkSemaphore::Resource* resource = vkSem->getResource();
+ GrVkSemaphore::Resource* resource = vkSem->getResource();
+ if (resource->shouldSignal()) {
resource->ref();
fSemaphoresToSignal.push_back(resource);
}
@@ -2181,13 +2182,14 @@ void GrVkGpu::onInsertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush) {
}
}
-void GrVkGpu::onWaitSemaphore(sk_sp<GrSemaphore> semaphore) {
+void GrVkGpu::waitSemaphore(sk_sp<GrSemaphore> semaphore) {
GrVkSemaphore* vkSem = static_cast<GrVkSemaphore*>(semaphore.get());
- SkASSERT(vkSem);
- const GrVkSemaphore::Resource* resource = vkSem->getResource();
- resource->ref();
- fSemaphoresToWaitOn.push_back(resource);
+ GrVkSemaphore::Resource* resource = vkSem->getResource();
+ if (resource->shouldWait()) {
+ resource->ref();
+ fSemaphoresToWaitOn.push_back(resource);
+ }
}
sk_sp<GrSemaphore> GrVkGpu::prepareTextureForCrossContextUsage(GrTexture* texture) {
diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h
index e3055945bc..8cc98d9da1 100644
--- a/src/gpu/vk/GrVkGpu.h
+++ b/src/gpu/vk/GrVkGpu.h
@@ -135,6 +135,12 @@ public:
void deleteFence(GrFence) const override;
sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT makeSemaphore(bool isOwned) override;
+ sk_sp<GrSemaphore> wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
+ GrResourceProvider::SemaphoreWrapType wrapType,
+ GrWrapOwnership ownership) override;
+ void insertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush) override;
+ void waitSemaphore(sk_sp<GrSemaphore> semaphore) override;
+
sk_sp<GrSemaphore> prepareTextureForCrossContextUsage(GrTexture*) override;
void generateMipmap(GrVkTexture* tex, GrSurfaceOrigin texOrigin);
@@ -204,11 +210,6 @@ private:
void onFinishFlush(bool insertedSemaphores) override;
- void onInsertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush) override;
- void onWaitSemaphore(sk_sp<GrSemaphore> semaphore) override;
- sk_sp<GrSemaphore> onWrapBackendSemaphore(const GrBackendSemaphore& semaphore,
- GrWrapOwnership ownership) 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
@@ -265,8 +266,8 @@ private:
GrVkPrimaryCommandBuffer* fCurrentCmdBuffer;
- SkSTArray<1, const GrVkSemaphore::Resource*> fSemaphoresToWaitOn;
- SkSTArray<1, const GrVkSemaphore::Resource*> fSemaphoresToSignal;
+ SkSTArray<1, GrVkSemaphore::Resource*> fSemaphoresToWaitOn;
+ SkSTArray<1, GrVkSemaphore::Resource*> fSemaphoresToSignal;
VkPhysicalDeviceMemoryProperties fPhysDevMemProps;
diff --git a/src/gpu/vk/GrVkSemaphore.cpp b/src/gpu/vk/GrVkSemaphore.cpp
index 38946f4566..4a23c43eea 100644
--- a/src/gpu/vk/GrVkSemaphore.cpp
+++ b/src/gpu/vk/GrVkSemaphore.cpp
@@ -16,6 +16,8 @@
#undef CreateSemaphore
#endif
+SkMutex GrVkSemaphore::Resource::gMutex;
+
sk_sp<GrVkSemaphore> GrVkSemaphore::Make(const GrVkGpu* gpu, bool isOwned) {
VkSemaphoreCreateInfo createInfo;
memset(&createInfo, 0, sizeof(VkSemaphoreCreateInfo));
@@ -26,22 +28,26 @@ sk_sp<GrVkSemaphore> GrVkSemaphore::Make(const GrVkGpu* gpu, bool isOwned) {
GR_VK_CALL_ERRCHECK(gpu->vkInterface(),
CreateSemaphore(gpu->device(), &createInfo, nullptr, &semaphore));
- return sk_sp<GrVkSemaphore>(new GrVkSemaphore(gpu, semaphore, isOwned));
+ return sk_sp<GrVkSemaphore>(new GrVkSemaphore(gpu, semaphore, false, false, isOwned));
}
sk_sp<GrVkSemaphore> GrVkSemaphore::MakeWrapped(const GrVkGpu* gpu,
VkSemaphore semaphore,
+ WrapType wrapType,
GrWrapOwnership ownership) {
if (VK_NULL_HANDLE == semaphore) {
return nullptr;
}
- return sk_sp<GrVkSemaphore>(new GrVkSemaphore(gpu, semaphore,
+ bool prohibitSignal = WrapType::kWillWait == wrapType;
+ bool prohibitWait = WrapType::kWillSignal == wrapType;
+ return sk_sp<GrVkSemaphore>(new GrVkSemaphore(gpu, semaphore, prohibitSignal, prohibitWait,
kBorrow_GrWrapOwnership != ownership));
}
-GrVkSemaphore::GrVkSemaphore(const GrVkGpu* gpu, VkSemaphore semaphore, bool isOwned)
+GrVkSemaphore::GrVkSemaphore(const GrVkGpu* gpu, VkSemaphore semaphore, bool prohibitSignal,
+ bool prohibitWait, bool isOwned)
: INHERITED(gpu) {
- fResource = new Resource(semaphore, isOwned);
+ fResource = new Resource(semaphore, prohibitSignal, prohibitWait, isOwned);
}
GrVkSemaphore::~GrVkSemaphore() {
diff --git a/src/gpu/vk/GrVkSemaphore.h b/src/gpu/vk/GrVkSemaphore.h
index b99eb944f7..36d1e6ee5d 100644
--- a/src/gpu/vk/GrVkSemaphore.h
+++ b/src/gpu/vk/GrVkSemaphore.h
@@ -9,6 +9,8 @@
#define GrVkSemaphore_DEFINED
#include "GrSemaphore.h"
+
+#include "GrResourceProvider.h"
#include "GrVkResource.h"
#include "vk/GrVkTypes.h"
@@ -20,21 +22,47 @@ class GrVkSemaphore : public GrSemaphore {
public:
static sk_sp<GrVkSemaphore> Make(const GrVkGpu* gpu, bool isOwned);
+ using WrapType = GrResourceProvider::SemaphoreWrapType;
+
static sk_sp<GrVkSemaphore> MakeWrapped(const GrVkGpu* gpu,
VkSemaphore semaphore,
+ WrapType wrapType,
GrWrapOwnership);
~GrVkSemaphore() override;
class Resource : public GrVkResource {
public:
- Resource(VkSemaphore semaphore, bool isOwned)
- : INHERITED(), fSemaphore(semaphore), fIsOwned(isOwned) {}
+ Resource(VkSemaphore semaphore, bool prohibitSignal, bool prohibitWait, bool isOwned)
+ : INHERITED()
+ , fSemaphore(semaphore)
+ , fHasBeenSubmittedToQueueForSignal(prohibitSignal)
+ , fHasBeenSubmittedToQueueForWait(prohibitWait)
+ , fIsOwned(isOwned) {}
~Resource() override {}
VkSemaphore semaphore() const { return fSemaphore; }
+ static void AcquireMutex() { gMutex.acquire(); }
+ static void ReleaseMutex() { gMutex.release(); }
+
+ bool shouldSignal() const {
+ return !fHasBeenSubmittedToQueueForSignal;
+ }
+ bool shouldWait() const {
+ return !fHasBeenSubmittedToQueueForWait;
+ }
+
+ void markAsSignaled() {
+ gMutex.assertHeld();
+ fHasBeenSubmittedToQueueForSignal = true;
+ }
+ void markAsWaited() {
+ gMutex.assertHeld();
+ fHasBeenSubmittedToQueueForWait = true;
+ }
+
#ifdef SK_TRACE_VK_RESOURCES
void dumpInfo() const override {
SkDebugf("GrVkSemaphore: %d (%d refs)\n", fSemaphore, this->getRefCnt());
@@ -43,20 +71,24 @@ public:
private:
void freeGPUData(const GrVkGpu* gpu) const override;
+ static SkMutex gMutex;
VkSemaphore fSemaphore;
+ bool fHasBeenSubmittedToQueueForSignal;
+ bool fHasBeenSubmittedToQueueForWait;
bool fIsOwned;
typedef GrVkResource INHERITED;
};
- const Resource* getResource() const { return fResource; }
+ Resource* getResource() { return fResource; }
private:
- GrVkSemaphore(const GrVkGpu* gpu, VkSemaphore semaphore, bool isOwned);
+ GrVkSemaphore(const GrVkGpu* gpu, VkSemaphore semaphore, bool prohibitSignal, bool prohibitWait,
+ bool isOwned);
void setBackendSemaphore(GrBackendSemaphore*) const override;
- const Resource* fResource;
+ Resource* fResource;
typedef GrSemaphore INHERITED;
};
diff --git a/tests/ImageTest.cpp b/tests/ImageTest.cpp
index 83ff47c256..6cc0fee4d9 100644
--- a/tests/ImageTest.cpp
+++ b/tests/ImageTest.cpp
@@ -894,12 +894,11 @@ static void test_cross_context_image(skiatest::Reporter* reporter, const GrConte
proxy.reset(nullptr);
proxySecondRef.reset(nullptr);
- // Now we should still fail to be able to borrow the texture from the other context
- // since only one context can ever borrow
+ // Now we should be able to borrow the texture from the other context
otherTestContext->makeCurrent();
otherProxy = as_IB(refImg)->asTextureProxyRef(otherCtx, GrSamplerState::ClampNearest(),
nullptr, &texColorSpace, nullptr);
- REPORTER_ASSERT(reporter, !otherProxy);
+ REPORTER_ASSERT(reporter, otherProxy);
// Release everything
otherProxy.reset(nullptr);