Update GrSemaphore to allow it to only be used once for signaling and once for waiting.
This is required for Vulkan which doesn't allow a semaphore to be waited on by multiple things at once or signaled from multiple places. Bug: skia: Change-Id: Iac0cb782a6662167c2cab1fd6a2c80378834a480 Reviewed-on: https://skia-review.googlesource.com/92601 Commit-Queue: Greg Daniel <egdaniel@google.com> Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
parent
e48eb337e1
commit
17b7c05433
@ -114,7 +114,8 @@ sk_sp<GrTextureProxy> GrBackendTextureImageGenerator::onGenerateTexture(
|
||||
} else {
|
||||
// Wait on a semaphore when a new context has just started borrowing the texture. This
|
||||
// is conservative, but shouldn't be too expensive.
|
||||
if (fSemaphore && fLastBorrowingContextID != context->uniqueID()) {
|
||||
if (fSemaphore && !fSemaphore->hasSubmittedWait() &&
|
||||
fLastBorrowingContextID != context->uniqueID()) {
|
||||
context->getGpu()->waitSemaphore(fSemaphore);
|
||||
fLastBorrowingContextID = context->uniqueID();
|
||||
}
|
||||
|
@ -488,7 +488,8 @@ GrSemaphoresSubmitted GrGpu::finishFlush(int numSemaphores,
|
||||
sk_sp<GrSemaphore> semaphore;
|
||||
if (backendSemaphores[i].isInitialized()) {
|
||||
semaphore = fContext->resourceProvider()->wrapBackendSemaphore(
|
||||
backendSemaphores[i], kBorrow_GrWrapOwnership);
|
||||
backendSemaphores[i], GrResourceProvider::SemaphoreWrapType::kWillSignal,
|
||||
kBorrow_GrWrapOwnership);
|
||||
} else {
|
||||
semaphore = fContext->resourceProvider()->makeSemaphore(false);
|
||||
}
|
||||
@ -513,3 +514,49 @@ 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;
|
||||
}
|
||||
|
||||
|
@ -377,10 +377,11 @@ public:
|
||||
virtual void deleteFence(GrFence) const = 0;
|
||||
|
||||
virtual sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT makeSemaphore(bool isOwned = true) = 0;
|
||||
virtual sk_sp<GrSemaphore> wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
|
||||
GrWrapOwnership ownership) = 0;
|
||||
virtual void insertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush = false) = 0;
|
||||
virtual void waitSemaphore(sk_sp<GrSemaphore> semaphore) = 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);
|
||||
|
||||
/**
|
||||
* Put this texture in a safe and known state for use across multiple GrContexts. Depending on
|
||||
@ -605,6 +606,11 @@ 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() {
|
||||
|
@ -1428,7 +1428,8 @@ bool GrRenderTargetContext::waitOnSemaphores(int numSemaphores,
|
||||
SkTArray<sk_sp<GrSemaphore>> semaphores(numSemaphores);
|
||||
for (int i = 0; i < numSemaphores; ++i) {
|
||||
sk_sp<GrSemaphore> sema = fContext->resourceProvider()->wrapBackendSemaphore(
|
||||
waitSemaphores[i], kAdopt_GrWrapOwnership);
|
||||
waitSemaphores[i], GrResourceProvider::SemaphoreWrapType::kWillWait,
|
||||
kAdopt_GrWrapOwnership);
|
||||
std::unique_ptr<GrOp> waitOp(GrSemaphoreOp::MakeWait(sema, fRenderTargetProxy.get()));
|
||||
this->getRTOpList()->addOp(std::move(waitOp), *this->caps());
|
||||
}
|
||||
|
@ -472,9 +472,12 @@ sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT GrResourceProvider::makeSemaphore(bool
|
||||
}
|
||||
|
||||
sk_sp<GrSemaphore> GrResourceProvider::wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
|
||||
SemaphoreWrapType wrapType,
|
||||
GrWrapOwnership ownership) {
|
||||
ASSERT_SINGLE_OWNER
|
||||
return this->isAbandoned() ? nullptr : fGpu->wrapBackendSemaphore(semaphore, ownership);
|
||||
return this->isAbandoned() ? nullptr : fGpu->wrapBackendSemaphore(semaphore,
|
||||
wrapType,
|
||||
ownership);
|
||||
}
|
||||
|
||||
void GrResourceProvider::takeOwnershipOfSemaphore(sk_sp<GrSemaphore> semaphore) {
|
||||
|
@ -228,7 +228,13 @@ public:
|
||||
|
||||
sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT makeSemaphore(bool isOwned = true);
|
||||
|
||||
enum class SemaphoreWrapType {
|
||||
kWillSignal,
|
||||
kWillWait,
|
||||
};
|
||||
|
||||
sk_sp<GrSemaphore> wrapBackendSemaphore(const GrBackendSemaphore&,
|
||||
SemaphoreWrapType wrapType,
|
||||
GrWrapOwnership = kBorrow_GrWrapOwnership);
|
||||
|
||||
// Takes the GrSemaphore and sets the ownership of the semaphore to the GrGpu object used by
|
||||
|
@ -13,7 +13,15 @@
|
||||
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,
|
||||
@ -26,6 +34,9 @@ private:
|
||||
// internal semaphore.
|
||||
virtual void setBackendSemaphore(GrBackendSemaphore*) const = 0;
|
||||
|
||||
bool fSignaled = false;
|
||||
bool fWaitedOn = false;
|
||||
|
||||
protected:
|
||||
explicit GrSemaphore(const GrGpu* gpu) : fGpu(gpu) {}
|
||||
|
||||
|
@ -72,17 +72,6 @@ public:
|
||||
SkASSERT(0);
|
||||
return nullptr;
|
||||
}
|
||||
sk_sp<GrSemaphore> wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
|
||||
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;
|
||||
@ -158,6 +147,18 @@ 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;
|
||||
|
@ -4569,26 +4569,29 @@ sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT GrGLGpu::makeSemaphore(bool isOwned) {
|
||||
return GrGLSemaphore::Make(this, isOwned);
|
||||
}
|
||||
|
||||
sk_sp<GrSemaphore> GrGLGpu::wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
|
||||
GrWrapOwnership ownership) {
|
||||
sk_sp<GrSemaphore> GrGLGpu::onWrapBackendSemaphore(const GrBackendSemaphore& semaphore,
|
||||
GrWrapOwnership ownership) {
|
||||
SkASSERT(this->caps()->fenceSyncSupport());
|
||||
return GrGLSemaphore::MakeWrapped(this, semaphore.glSync(), ownership);
|
||||
}
|
||||
|
||||
void GrGLGpu::insertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush) {
|
||||
void GrGLGpu::onInsertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush) {
|
||||
GrGLSemaphore* glSem = static_cast<GrGLSemaphore*>(semaphore.get());
|
||||
|
||||
GrGLsync sync;
|
||||
GL_CALL_RET(sync, FenceSync(GR_GL_SYNC_GPU_COMMANDS_COMPLETE, 0));
|
||||
glSem->setSync(sync);
|
||||
if (glSem) {
|
||||
GrGLsync sync;
|
||||
GL_CALL_RET(sync, FenceSync(GR_GL_SYNC_GPU_COMMANDS_COMPLETE, 0));
|
||||
glSem->setSync(sync);
|
||||
}
|
||||
|
||||
if (flush) {
|
||||
GL_CALL(Flush());
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLGpu::waitSemaphore(sk_sp<GrSemaphore> semaphore) {
|
||||
void GrGLGpu::onWaitSemaphore(sk_sp<GrSemaphore> semaphore) {
|
||||
GrGLSemaphore* glSem = static_cast<GrGLSemaphore*>(semaphore.get());
|
||||
SkASSERT(glSem);
|
||||
|
||||
GL_CALL(WaitSync(glSem->sync(), 0, GR_GL_TIMEOUT_IGNORED));
|
||||
}
|
||||
|
@ -173,10 +173,6 @@ public:
|
||||
void deleteFence(GrFence) const override;
|
||||
|
||||
sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT makeSemaphore(bool isOwned) override;
|
||||
sk_sp<GrSemaphore> wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
|
||||
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;
|
||||
|
||||
@ -290,6 +286,11 @@ 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,
|
||||
|
@ -58,10 +58,6 @@ public:
|
||||
sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT makeSemaphore(bool isOwned) override {
|
||||
return nullptr;
|
||||
}
|
||||
sk_sp<GrSemaphore> wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
|
||||
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*);
|
||||
@ -124,6 +120,11 @@ 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;
|
||||
|
@ -67,10 +67,6 @@ public:
|
||||
sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT makeSemaphore(bool isOwned) override {
|
||||
return nullptr;
|
||||
}
|
||||
sk_sp<GrSemaphore> wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
|
||||
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:
|
||||
@ -133,6 +129,11 @@ 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 {
|
||||
|
@ -2162,25 +2162,28 @@ sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT GrVkGpu::makeSemaphore(bool isOwned) {
|
||||
return GrVkSemaphore::Make(this, isOwned);
|
||||
}
|
||||
|
||||
sk_sp<GrSemaphore> GrVkGpu::wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
|
||||
GrWrapOwnership ownership) {
|
||||
sk_sp<GrSemaphore> GrVkGpu::onWrapBackendSemaphore(const GrBackendSemaphore& semaphore,
|
||||
GrWrapOwnership ownership) {
|
||||
return GrVkSemaphore::MakeWrapped(this, semaphore.vkSemaphore(), ownership);
|
||||
}
|
||||
|
||||
void GrVkGpu::insertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush) {
|
||||
void GrVkGpu::onInsertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush) {
|
||||
GrVkSemaphore* vkSem = static_cast<GrVkSemaphore*>(semaphore.get());
|
||||
|
||||
const GrVkSemaphore::Resource* resource = vkSem->getResource();
|
||||
resource->ref();
|
||||
fSemaphoresToSignal.push_back(resource);
|
||||
if (vkSem) {
|
||||
const GrVkSemaphore::Resource* resource = vkSem->getResource();
|
||||
resource->ref();
|
||||
fSemaphoresToSignal.push_back(resource);
|
||||
}
|
||||
|
||||
if (flush) {
|
||||
this->submitCommandBuffer(kSkip_SyncQueue);
|
||||
}
|
||||
}
|
||||
|
||||
void GrVkGpu::waitSemaphore(sk_sp<GrSemaphore> semaphore) {
|
||||
void GrVkGpu::onWaitSemaphore(sk_sp<GrSemaphore> semaphore) {
|
||||
GrVkSemaphore* vkSem = static_cast<GrVkSemaphore*>(semaphore.get());
|
||||
SkASSERT(vkSem);
|
||||
|
||||
const GrVkSemaphore::Resource* resource = vkSem->getResource();
|
||||
resource->ref();
|
||||
|
@ -135,11 +135,6 @@ public:
|
||||
void deleteFence(GrFence) const override;
|
||||
|
||||
sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT makeSemaphore(bool isOwned) override;
|
||||
sk_sp<GrSemaphore> wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
|
||||
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);
|
||||
@ -209,6 +204,11 @@ 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
|
||||
|
Loading…
Reference in New Issue
Block a user