Add optional param to setBackendTextureState to return previous state.

Bug: skia:10742
Change-Id: I334e7896d0a1509eb666c46d5731d2573a5c1aba
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/318698
Reviewed-by: Austin Eng <enga@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
This commit is contained in:
Greg Daniel 2020-09-23 14:23:36 -04:00 committed by Skia Commit-Bot
parent 7b97b3cb2b
commit 1d3c8c1a8b
10 changed files with 142 additions and 29 deletions

View File

@ -9,6 +9,10 @@ Milestone 87
* <insert new release notes here>
* Add new optional parameter to GrContext::setBackend[Texture/RenderTarget]State which can
be used to return the previous GrBackendSurfaceMutableState before the requested change.
https://review.skia.org/318698
* New optimized clip stack for GPU backends. Enabled by default but old behavior based on
SkClipStack can be restored by defining SK_DISABLE_NEW_GR_CLIP_STACK when building. It is not
compatible with SK_SUPPORT_DEPRECATED_CLIPOPS and we are targeting the removal of support for

View File

@ -38,6 +38,7 @@ skia_gpu_sources = [
"$_src/gpu/GrAutoLocaleSetter.h",
"$_src/gpu/GrBackendSemaphore.cpp",
"$_src/gpu/GrBackendSurface.cpp",
"$_src/gpu/GrBackendSurfaceMutableState.cpp",
"$_src/gpu/GrBackendSurfaceMutableStateImpl.h",
"$_src/gpu/GrBackendTextureImageGenerator.cpp",
"$_src/gpu/GrBackendTextureImageGenerator.h",

View File

@ -24,35 +24,59 @@
*
* Vulkan: VkImageLayout and QueueFamilyIndex
*/
class GrBackendSurfaceMutableState {
class SK_API GrBackendSurfaceMutableState {
public:
GrBackendSurfaceMutableState() {}
#ifdef SK_VULKAN
GrBackendSurfaceMutableState(VkImageLayout layout, uint32_t queueFamilyIndex)
: fVkState(layout, queueFamilyIndex)
, fBackend(GrBackend::kVulkan) {}
, fBackend(GrBackend::kVulkan)
, fIsValid(true) {}
#endif
GrBackendSurfaceMutableState& operator=(const GrBackendSurfaceMutableState& that) {
switch (fBackend) {
case GrBackend::kVulkan:
GrBackendSurfaceMutableState(const GrBackendSurfaceMutableState& that);
GrBackendSurfaceMutableState& operator=(const GrBackendSurfaceMutableState& that);
#ifdef SK_VULKAN
SkASSERT(that.fBackend == GrBackend::kVulkan);
fVkState = that.fVkState;
#endif
break;
default:
(void)that;
SkUNREACHABLE;
// If this class is not Vulkan backed it will return value of VK_IMAGE_LAYOUT_UNDEFINED.
// Otherwise it will return the VkImageLayout.
VkImageLayout getVkImageLayout() const {
if (this->isValid() && fBackend != GrBackendApi::kVulkan) {
return VK_IMAGE_LAYOUT_UNDEFINED;
}
fBackend = that.fBackend;
return *this;
return fVkState.getImageLayout();
}
// If this class is not Vulkan backed it will return value of VK_QUEUE_FAMILY_IGNORED.
// Otherwise it will return the VkImageLayout.
uint32_t getQueueFamilyIndex() const {
if (this->isValid() && fBackend != GrBackendApi::kVulkan) {
return VK_QUEUE_FAMILY_IGNORED;
}
return fVkState.getQueueFamilyIndex();
}
#endif
// Returns true if the backend mutable state has been initialized.
bool isValid() const { return fIsValid; }
GrBackendApi backend() const { return fBackend; }
private:
friend class GrBackendSurfaceMutableStateImpl;
friend class GrVkGpu;
#ifdef SK_VULKAN
void setVulkanState(VkImageLayout layout, uint32_t queueFamilyIndex) {
SkASSERT(!this->isValid() || fBackend == GrBackendApi::kVulkan);
fVkState.setImageLayout(layout);
fVkState.setQueueFamilyIndex(queueFamilyIndex);
fBackend = GrBackendApi::kVulkan;
fIsValid = true;
}
#endif
union {
char fDummy;
#ifdef SK_VULKAN
@ -60,7 +84,8 @@ private:
#endif
};
GrBackend fBackend;
GrBackend fBackend = GrBackendApi::kMock;
bool fIsValid = false;
};
#endif

View File

@ -687,18 +687,23 @@ public:
* called (e.g updateBackendTexture and flush). If finishedProc is not null then it will be
* called with finishedContext after the state transition is known to have occurred on the GPU.
*
* See GrBackendSurfaceMutableState to see what state can be set via this call.
*
* If the backend API is Vulkan, the caller can set the GrBackendSurfaceMutableState's
* VkImageLayout to VK_IMAGE_LAYOUT_UNDEFINED or queueFamilyIndex to VK_QUEUE_FAMILY_IGNORED to
* tell Skia to not change those respective states.
*
* See GrBackendSurfaceMutableState to see what state can be set via this call.
* If previousState is not null and this returns true, then Skia will have filled in
* previousState to have the values of the state before this call.
*/
bool setBackendTextureState(const GrBackendTexture&,
const GrBackendSurfaceMutableState&,
GrBackendSurfaceMutableState* previousState = nullptr,
GrGpuFinishedProc finishedProc = nullptr,
GrGpuFinishedContext finishedContext = nullptr);
bool setBackendRenderTargetState(const GrBackendRenderTarget&,
const GrBackendSurfaceMutableState&,
GrBackendSurfaceMutableState* previousState = nullptr,
GrGpuFinishedProc finishedProc = nullptr,
GrGpuFinishedContext finishedContext = nullptr);

View File

@ -0,0 +1,38 @@
/*
* Copyright 2020 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/gpu/GrBackendSurfaceMutableState.h"
#include <new>
GrBackendSurfaceMutableState::GrBackendSurfaceMutableState(const GrBackendSurfaceMutableState& that)
: fBackend(that.fBackend), fIsValid(that.fIsValid) {
if (!fIsValid) {
return;
}
switch (fBackend) {
case GrBackend::kVulkan:
#ifdef SK_VULKAN
SkASSERT(that.fBackend == GrBackend::kVulkan);
fVkState = that.fVkState;
#endif
break;
default:
(void)that;
SkUNREACHABLE;
}
}
GrBackendSurfaceMutableState& GrBackendSurfaceMutableState::operator=(
const GrBackendSurfaceMutableState& that) {
if (this != &that) {
this->~GrBackendSurfaceMutableState();
new (this) GrBackendSurfaceMutableState(that);
}
return *this;
}

View File

@ -754,6 +754,7 @@ GrBackendTexture GrContext::createCompressedBackendTexture(int width, int height
bool GrContext::setBackendTextureState(const GrBackendTexture& backendTexture,
const GrBackendSurfaceMutableState& state,
GrBackendSurfaceMutableState* previousState,
GrGpuFinishedProc finishedProc,
GrGpuFinishedContext finishedContext) {
sk_sp<GrRefCntedCallback> callback;
@ -769,7 +770,7 @@ bool GrContext::setBackendTextureState(const GrBackendTexture& backendTexture,
return false;
}
return fGpu->setBackendTextureState(backendTexture, state, std::move(callback));
return fGpu->setBackendTextureState(backendTexture, state, previousState, std::move(callback));
}
bool GrContext::updateCompressedBackendTexture(const GrBackendTexture& backendTexture,
@ -824,6 +825,7 @@ bool GrContext::updateCompressedBackendTexture(const GrBackendTexture& backendTe
bool GrContext::setBackendRenderTargetState(const GrBackendRenderTarget& backendRenderTarget,
const GrBackendSurfaceMutableState& state,
GrBackendSurfaceMutableState* previousState,
GrGpuFinishedProc finishedProc,
GrGpuFinishedContext finishedContext) {
sk_sp<GrRefCntedCallback> callback;
@ -839,7 +841,8 @@ bool GrContext::setBackendRenderTargetState(const GrBackendRenderTarget& backend
return false;
}
return fGpu->setBackendRenderTargetState(backendRenderTarget, state, std::move(callback));
return fGpu->setBackendRenderTargetState(backendRenderTarget, state, previousState,
std::move(callback));
}
void GrContext::deleteBackendTexture(GrBackendTexture backendTex) {

View File

@ -635,12 +635,14 @@ public:
virtual bool setBackendTextureState(const GrBackendTexture&,
const GrBackendSurfaceMutableState&,
GrBackendSurfaceMutableState* previousState,
sk_sp<GrRefCntedCallback> finishedCallback) {
return false;
}
virtual bool setBackendRenderTargetState(const GrBackendRenderTarget&,
const GrBackendSurfaceMutableState&,
GrBackendSurfaceMutableState* previousState,
sk_sp<GrRefCntedCallback> finishedCallback) {
return false;
}

View File

@ -1816,7 +1816,8 @@ void set_layout_and_queue_from_mutable_state(GrVkGpu* gpu, GrVkImage* image,
bool GrVkGpu::setBackendSurfaceState(GrVkImageInfo info,
sk_sp<GrBackendSurfaceMutableStateImpl> currentState,
SkISize dimensions,
const GrVkSharedImageInfo& newInfo) {
const GrVkSharedImageInfo& newInfo,
GrBackendSurfaceMutableState* previousState) {
sk_sp<GrVkTexture> texture = GrVkTexture::MakeWrappedTexture(
this, dimensions, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, kRW_GrIOType, info,
std::move(currentState));
@ -1824,32 +1825,39 @@ bool GrVkGpu::setBackendSurfaceState(GrVkImageInfo info,
if (!texture) {
return false;
}
if (previousState) {
previousState->setVulkanState(texture->currentLayout(),
texture->currentQueueFamilyIndex());
}
set_layout_and_queue_from_mutable_state(this, texture.get(), newInfo);
return true;
}
bool GrVkGpu::setBackendTextureState(const GrBackendTexture& backendTeture,
const GrBackendSurfaceMutableState& newState,
GrBackendSurfaceMutableState* previousState,
sk_sp<GrRefCntedCallback> finishedCallback) {
GrVkImageInfo info;
SkAssertResult(backendTeture.getVkImageInfo(&info));
sk_sp<GrBackendSurfaceMutableStateImpl> currentState = backendTeture.getMutableState();
SkASSERT(currentState);
SkASSERT(newState.fBackend == GrBackend::kVulkan);
SkASSERT(newState.isValid() && newState.fBackend == GrBackend::kVulkan);
return this->setBackendSurfaceState(info, std::move(currentState), backendTeture.dimensions(),
newState.fVkState);
newState.fVkState, previousState);
}
bool GrVkGpu::setBackendRenderTargetState(const GrBackendRenderTarget& backendRenderTarget,
const GrBackendSurfaceMutableState& newState,
sk_sp<GrRefCntedCallback> finishedCallback) {
GrBackendSurfaceMutableState* previousState,
sk_sp<GrRefCntedCallback> finishedCallback) {
GrVkImageInfo info;
SkAssertResult(backendRenderTarget.getVkImageInfo(&info));
sk_sp<GrBackendSurfaceMutableStateImpl> currentState = backendRenderTarget.getMutableState();
SkASSERT(currentState);
SkASSERT(newState.fBackend == GrBackend::kVulkan);
return this->setBackendSurfaceState(info, std::move(currentState),
backendRenderTarget.dimensions(), newState.fVkState);
backendRenderTarget.dimensions(), newState.fVkState,
previousState);
}
void GrVkGpu::querySampleLocations(GrRenderTarget* renderTarget,

View File

@ -79,10 +79,12 @@ public:
bool setBackendTextureState(const GrBackendTexture&,
const GrBackendSurfaceMutableState&,
GrBackendSurfaceMutableState* previousState,
sk_sp<GrRefCntedCallback> finishedCallback) override;
bool setBackendRenderTargetState(const GrBackendRenderTarget&,
const GrBackendSurfaceMutableState&,
GrBackendSurfaceMutableState* previousState,
sk_sp<GrRefCntedCallback> finishedCallback) override;
void deleteBackendTexture(const GrBackendTexture&) override;
@ -215,7 +217,8 @@ private:
bool setBackendSurfaceState(GrVkImageInfo info,
sk_sp<GrBackendSurfaceMutableStateImpl> currentState,
SkISize dimensions,
const GrVkSharedImageInfo& newInfo);
const GrVkSharedImageInfo& newInfo,
GrBackendSurfaceMutableState* previousState);
sk_sp<GrTexture> onCreateTexture(SkISize,
const GrBackendFormat&,

View File

@ -107,41 +107,65 @@ DEF_GPUTEST_FOR_VULKAN_CONTEXT(VkBackendSurfaceMutableStateTest, reporter, ctxIn
// real transitions to the image so we need to be careful about doing actual valid transitions.
GrVkGpu* gpu = static_cast<GrVkGpu*>(dContext->priv().getGpu());
dContext->setBackendTextureState(backendTex, newState);
GrBackendSurfaceMutableState previousState;
dContext->setBackendTextureState(backendTex, newState, &previousState);
REPORTER_ASSERT(reporter, backendTex.getVkImageInfo(&info));
REPORTER_ASSERT(reporter, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == info.fImageLayout);
REPORTER_ASSERT(reporter, gpu->queueIndex() == info.fCurrentQueueFamily);
REPORTER_ASSERT(reporter, previousState.isValid());
REPORTER_ASSERT(reporter, previousState.backend() == GrBackendApi::kVulkan);
REPORTER_ASSERT(reporter, previousState.getVkImageLayout() == initLayout);
REPORTER_ASSERT(reporter, previousState.getQueueFamilyIndex() == initQueue);
// Make sure passing in VK_IMAGE_LAYOUT_UNDEFINED does not change the layout
GrBackendSurfaceMutableState noopState(VK_IMAGE_LAYOUT_UNDEFINED, VK_QUEUE_FAMILY_IGNORED);
dContext->setBackendTextureState(backendTex, noopState);
dContext->setBackendTextureState(backendTex, noopState, &previousState);
REPORTER_ASSERT(reporter, backendTex.getVkImageInfo(&info));
REPORTER_ASSERT(reporter, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == info.fImageLayout);
REPORTER_ASSERT(reporter, gpu->queueIndex() == info.fCurrentQueueFamily);
REPORTER_ASSERT(reporter, previousState.isValid());
REPORTER_ASSERT(reporter, previousState.backend() == GrBackendApi::kVulkan);
REPORTER_ASSERT(reporter,
previousState.getVkImageLayout() == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
REPORTER_ASSERT(reporter, previousState.getQueueFamilyIndex() == gpu->queueIndex());
// To test queue transitions, we don't have any other valid queue available so instead we try
// to transition to external queue.
if (gpu->vkCaps().supportsExternalMemory()) {
GrBackendSurfaceMutableState externalState(VK_IMAGE_LAYOUT_GENERAL,
VK_QUEUE_FAMILY_EXTERNAL);
dContext->setBackendTextureState(backendTex, externalState);
dContext->setBackendTextureState(backendTex, externalState, &previousState);
REPORTER_ASSERT(reporter, backendTex.getVkImageInfo(&info));
REPORTER_ASSERT(reporter, VK_IMAGE_LAYOUT_GENERAL == info.fImageLayout);
REPORTER_ASSERT(reporter, VK_QUEUE_FAMILY_EXTERNAL == info.fCurrentQueueFamily);
REPORTER_ASSERT(reporter, previousState.isValid());
REPORTER_ASSERT(reporter, previousState.backend() == GrBackendApi::kVulkan);
REPORTER_ASSERT(reporter,
previousState.getVkImageLayout() == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
REPORTER_ASSERT(reporter, previousState.getQueueFamilyIndex() == gpu->queueIndex());
dContext->submit();
// Go back to the initial queue. Also we should stay in VK_IMAGE_LAYOUT_GENERAL since we
// are passing in VK_IMAGE_LAYOUT_UNDEFINED
GrBackendSurfaceMutableState externalState2(VK_IMAGE_LAYOUT_UNDEFINED, initQueue);
dContext->setBackendTextureState(backendTex, externalState2);
dContext->setBackendTextureState(backendTex, externalState2, &previousState);
REPORTER_ASSERT(reporter, backendTex.getVkImageInfo(&info));
REPORTER_ASSERT(reporter, VK_IMAGE_LAYOUT_GENERAL == info.fImageLayout);
REPORTER_ASSERT(reporter, gpu->queueIndex() == info.fCurrentQueueFamily);
REPORTER_ASSERT(reporter, previousState.isValid());
REPORTER_ASSERT(reporter, previousState.backend() == GrBackendApi::kVulkan);
REPORTER_ASSERT(reporter, previousState.getVkImageLayout() == VK_IMAGE_LAYOUT_GENERAL);
REPORTER_ASSERT(reporter, previousState.getQueueFamilyIndex() == VK_QUEUE_FAMILY_EXTERNAL);
}
// We must submit this work before we try to delete the backend texture.