Add option for client to own semaphores after telling to skia to wait.

Bug: chromium:1004772
Change-Id: Ifdad0b12925d13d3e896f6321c35312f9daa330c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/301216
Commit-Queue: Greg Daniel <egdaniel@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
This commit is contained in:
Greg Daniel 2020-07-08 11:44:25 -04:00 committed by Skia Commit-Bot
parent 4e3ab796c4
commit 414418d55f
14 changed files with 73 additions and 39 deletions

View File

@ -7,6 +7,9 @@ This file includes a list of high level updates for each milestone release.
Milestone 86
------------
* Add option for clients to own semaphores after wait calls.
https://review.skia.org/301216
* Remove obsolete GrFlushFlags.
https://review.skia.org/298818

View File

@ -1014,16 +1014,22 @@ public:
void flush() { this->flush({}); }
/** Inserts a list of GPU semaphores that the current GPU-backed API must wait on before
executing any more commands on the GPU for this surface. Skia will take ownership of the
underlying semaphores and delete them once they have been signaled and waited on.
If this call returns false, then the GPU back-end will not wait on any passed in semaphores,
and the client will still own the semaphores.
executing any more commands on the GPU for this surface. If this call returns false, then
the GPU back-end will not wait on any passed in semaphores, and the client will still own
the semaphores, regardless of the value of deleteSemaphoresAfterWait.
@param numSemaphores size of waitSemaphores array
@param waitSemaphores array of semaphore containers
@return true if GPU is waiting on semaphores
If deleteSemaphoresAfterWait is false then Skia will not delete the semaphores. In this case
it is the client's responsibility to not destroy or attempt to reuse the semaphores until it
knows that Skia has finished waiting on them. This can be done by using finishedProcs
on flush calls.
@param numSemaphores size of waitSemaphores array
@param waitSemaphores array of semaphore containers
@paramm deleteSemaphoresAfterWait who owns and should delete the semaphores
@return true if GPU is waiting on semaphores
*/
bool wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores);
bool wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores,
bool deleteSemaphoresAfterWait = true);
/** Initializes SkSurfaceCharacterization that can be used to perform GPU back-end
processing in a separate thread. Typically this is used to divide drawing

View File

@ -321,12 +321,17 @@ public:
/**
* 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
* and delete them once they have been signaled and waited on. If this call returns false, then
* the GPU back-end will not wait on any passed in semaphores, and the client will still own the
* semaphores.
* executing any more commands on the GPU. If this call returns false, then the GPU back-end
* will not wait on any passed in semaphores, and the client will still own the semaphores,
* regardless of the value of deleteSemaphoresAfterWait.
*
* If deleteSemaphoresAfterWait is false then Skia will not delete the semaphores. In this case
* it is the client's responsibility to not destroy or attempt to reuse the semaphores until it
* knows that Skia has finished waiting on them. This can be done by using finishedProcs on
* flush calls.
*/
bool wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores);
bool wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores,
bool deleteSemaphoresAfterWait = true);
/**
* Call to ensure all drawing to the context has been flushed and submitted to the underlying 3D

View File

@ -290,14 +290,16 @@ int GrContext::maxSurfaceSampleCountForColorType(SkColorType colorType) const {
////////////////////////////////////////////////////////////////////////////////
bool GrContext::wait(int numSemaphores, const GrBackendSemaphore waitSemaphores[]) {
bool GrContext::wait(int numSemaphores, const GrBackendSemaphore waitSemaphores[],
bool deleteSemaphoresAfterWait) {
if (!fGpu || fGpu->caps()->semaphoreSupport()) {
return false;
}
GrWrapOwnership ownership =
deleteSemaphoresAfterWait ? kAdopt_GrWrapOwnership : kBorrow_GrWrapOwnership;
for (int i = 0; i < numSemaphores; ++i) {
std::unique_ptr<GrSemaphore> sema = fResourceProvider->wrapBackendSemaphore(
waitSemaphores[i], GrResourceProvider::SemaphoreWrapType::kWillWait,
kAdopt_GrWrapOwnership);
waitSemaphores[i], GrResourceProvider::SemaphoreWrapType::kWillWait, ownership);
// If we failed to wrap the semaphore it means the client didn't give us a valid semaphore
// to begin with. Therefore, it is fine to not wait on it.
if (sema) {

View File

@ -1705,7 +1705,8 @@ void GrRenderTargetContext::drawDrawable(std::unique_ptr<SkDrawable::GpuDrawHand
}
bool GrRenderTargetContext::waitOnSemaphores(int numSemaphores,
const GrBackendSemaphore waitSemaphores[]) {
const GrBackendSemaphore waitSemaphores[],
bool deleteSemaphoresAfterWait) {
ASSERT_SINGLE_OWNER
RETURN_FALSE_IF_ABANDONED
SkDEBUGCODE(this->validate();)
@ -1724,12 +1725,14 @@ bool GrRenderTargetContext::waitOnSemaphores(int numSemaphores,
auto resourceProvider = direct->priv().resourceProvider();
GrWrapOwnership ownership =
deleteSemaphoresAfterWait ? kAdopt_GrWrapOwnership : kBorrow_GrWrapOwnership;
std::unique_ptr<std::unique_ptr<GrSemaphore>[]> grSemaphores(
new std::unique_ptr<GrSemaphore>[numSemaphores]);
for (int i = 0; i < numSemaphores; ++i) {
grSemaphores[i] = resourceProvider->wrapBackendSemaphore(
waitSemaphores[i], GrResourceProvider::SemaphoreWrapType::kWillWait,
kAdopt_GrWrapOwnership);
waitSemaphores[i], GrResourceProvider::SemaphoreWrapType::kWillWait, ownership);
}
this->drawingManager()->newWaitRenderTask(this->asSurfaceProxyRef(), std::move(grSemaphores),
numSemaphores);

View File

@ -528,7 +528,8 @@ public:
* The next time this GrRenderTargetContext is flushed, the gpu will wait on the passed in
* semaphores before executing any commands.
*/
bool waitOnSemaphores(int numSemaphores, const GrBackendSemaphore waitSemaphores[]);
bool waitOnSemaphores(int numSemaphores, const GrBackendSemaphore waitSemaphores[],
bool deleteSemaphoresAfterWait);
int numSamples() const { return this->asRenderTargetProxy()->numSamples(); }
const SkSurfaceProps& surfaceProps() const { return fSurfaceProps; }

View File

@ -1027,10 +1027,12 @@ GrSemaphoresSubmitted SkGpuDevice::flush(SkSurface::BackendSurfaceAccess access,
return fRenderTargetContext->flush(access, info, newState);
}
bool SkGpuDevice::wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) {
bool SkGpuDevice::wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores,
bool deleteSemaphoresAfterWait) {
ASSERT_SINGLE_OWNER
return fRenderTargetContext->waitOnSemaphores(numSemaphores, waitSemaphores);
return fRenderTargetContext->waitOnSemaphores(numSemaphores, waitSemaphores,
deleteSemaphoresAfterWait);
}
///////////////////////////////////////////////////////////////////////////////

View File

@ -116,7 +116,8 @@ public:
void flush() override;
GrSemaphoresSubmitted flush(SkSurface::BackendSurfaceAccess access, const GrFlushInfo&,
const GrBackendSurfaceMutableState*);
bool wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores);
bool wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores,
bool deleteSemaphoresAfterWait);
bool onAccessPixels(SkPixmap*) override;

View File

@ -65,8 +65,9 @@ void GrVkSecondaryCBDrawContext::flush() {
}
bool GrVkSecondaryCBDrawContext::wait(int numSemaphores,
const GrBackendSemaphore waitSemaphores[]) {
return fDevice->wait(numSemaphores, waitSemaphores);
const GrBackendSemaphore waitSemaphores[],
bool deleteSemaphoresAfterWait) {
return fDevice->wait(numSemaphores, waitSemaphores, deleteSemaphoresAfterWait);
}
void GrVkSecondaryCBDrawContext::releaseResources() {

View File

@ -73,16 +73,22 @@ public:
commands for this secondary CB. The wait semaphores will get added to the VkCommandBuffer
owned by this GrContext when flush() is called, and not the command buffer which the
Secondary CB is from. This will guarantee that the driver waits on the semaphores before
the secondary command buffer gets executed. Skia will take ownership of the underlying
semaphores and delete them once they have been signaled and waited on. If this call returns
false, then the GPU back-end will not wait on any passed in semaphores, and the client will
still own the semaphores.
the secondary command buffer gets executed. If this call returns false, then the GPU
back end will not wait on any passed in semaphores, and the client will still own the
semaphores, regardless of the value of deleteSemaphoresAfterWait.
@param numSemaphores size of waitSemaphores array
@param waitSemaphores array of semaphore containers
@return true if GPU is waiting on semaphores
If deleteSemaphoresAfterWait is false then Skia will not delete the semaphores. In this case
it is the client's responsibility to not destroy or attempt to reuse the semaphores until it
knows that Skia has finished waiting on them. This can be done by using finishedProcs
on flush calls.
@param numSemaphores size of waitSemaphores array
@param waitSemaphores array of semaphore containers
@paramm deleteSemaphoresAfterWait who owns and should delete the semaphores
@return true if GPU is waiting on semaphores
*/
bool wait(int numSemaphores, const GrBackendSemaphore waitSemaphores[]);
bool wait(int numSemaphores, const GrBackendSemaphore waitSemaphores[],
bool deleteSemaphoresAfterWait = true);
// This call will release all resources held by the draw context. The client must call
// releaseResources() before deleting the drawing context. However, the resources also include

View File

@ -365,8 +365,9 @@ GrSemaphoresSubmitted SkSurface::flush(const GrFlushInfo& info,
return asSB(this)->onFlush(BackendSurfaceAccess::kNoAccess, info, newState);
}
bool SkSurface::wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) {
return asSB(this)->onWait(numSemaphores, waitSemaphores);
bool SkSurface::wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores,
bool deleteSemaphoresAfterWait) {
return asSB(this)->onWait(numSemaphores, waitSemaphores, deleteSemaphoresAfterWait);
}
bool SkSurface::characterize(SkSurfaceCharacterization* characterization) const {

View File

@ -119,7 +119,8 @@ public:
* commands on the gpu. Any previously submitting commands will not be blocked by these
* semaphores.
*/
virtual bool onWait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) {
virtual bool onWait(int numSemaphores, const GrBackendSemaphore* waitSemaphores,
bool deleteSemaphoresAfterWait) {
return false;
}

View File

@ -197,8 +197,9 @@ GrSemaphoresSubmitted SkSurface_Gpu::onFlush(BackendSurfaceAccess access, const
return fDevice->flush(access, info, newState);
}
bool SkSurface_Gpu::onWait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) {
return fDevice->wait(numSemaphores, waitSemaphores);
bool SkSurface_Gpu::onWait(int numSemaphores, const GrBackendSemaphore* waitSemaphores,
bool deleteSemaphoresAfterWait) {
return fDevice->wait(numSemaphores, waitSemaphores, deleteSemaphoresAfterWait);
}
bool SkSurface_Gpu::onCharacterize(SkSurfaceCharacterization* characterization) const {

View File

@ -54,7 +54,8 @@ public:
void onDiscard() override;
GrSemaphoresSubmitted onFlush(BackendSurfaceAccess access, const GrFlushInfo& info,
const GrBackendSurfaceMutableState*) override;
bool onWait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) override;
bool onWait(int numSemaphores, const GrBackendSemaphore* waitSemaphores,
bool deleteSemaphoresAfterWait) override;
bool onCharacterize(SkSurfaceCharacterization*) const override;
bool onIsCompatible(const SkSurfaceCharacterization&) const override;
void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) override;