Add GrContext API to allow updating GrBackendSurfaceMutableState.
This is currently only supported for the Vulkan backend Bug: skia:10254 Change-Id: I9274799098dc00dec5abcbcec95ce7cc23fec537 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/293844 Commit-Queue: Greg Daniel <egdaniel@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com>
This commit is contained in:
parent
4442bfa50b
commit
1db8e7990a
@ -8,9 +8,13 @@ Milestone 85
|
||||
------------
|
||||
|
||||
* <insert new release notes here>
|
||||
|
||||
|
||||
* Add GrContext function to set mutable state on a backend surface. Currently this
|
||||
is only used for setting vulkan VkImage layout and queue family.
|
||||
https://review.skia.org/293844
|
||||
|
||||
* SkSurface factores that take GrBackendTexture or GrBackendRenderTarget now always
|
||||
call the release proc (if provided) on failure. SkSurface::replaceBackendTexture
|
||||
call the release proc (if provided) on failure. SkSurface::replaceBackendTexture
|
||||
also calls the release proc on failure.
|
||||
https://review.skia.org/293762
|
||||
|
||||
|
@ -51,6 +51,7 @@ public:
|
||||
|
||||
private:
|
||||
friend class GrBackendSurfaceMutableStateImpl;
|
||||
friend class GrVkGpu;
|
||||
|
||||
union {
|
||||
char fDummy;
|
||||
|
@ -665,6 +665,26 @@ public:
|
||||
GrGpuFinishedProc finishedProc = nullptr,
|
||||
GrGpuFinishedContext finishedContext = nullptr);
|
||||
|
||||
/**
|
||||
* Updates the state of the GrBackendTexture/RenderTarget to have the passed in
|
||||
* GrBackendSurfaceMutableState. All objects that wrap the backend surface (i.e. SkSurfaces and
|
||||
* SkImages) will also be aware of this state change. This call does not submit the state change
|
||||
* to the gpu, but requires the client to call GrContext::submit to send it to the GPU. The work
|
||||
* for this call is ordered linearly with all other calls that require GrContext::submit to be
|
||||
* 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.
|
||||
*/
|
||||
bool setBackendTextureState(const GrBackendTexture&,
|
||||
const GrBackendSurfaceMutableState&,
|
||||
GrGpuFinishedProc finishedProc = nullptr,
|
||||
GrGpuFinishedContext finishedContext = nullptr);
|
||||
bool setBackendRenderTargetState(const GrBackendRenderTarget&,
|
||||
const GrBackendSurfaceMutableState&,
|
||||
GrGpuFinishedProc finishedProc = nullptr,
|
||||
GrGpuFinishedContext finishedContext = nullptr);
|
||||
|
||||
void deleteBackendTexture(GrBackendTexture);
|
||||
|
||||
// This interface allows clients to pre-compile shaders and populate the runtime program cache.
|
||||
|
@ -53,7 +53,6 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void setImageLayout(VkImageLayout layout) {
|
||||
// Defaulting to use std::memory_order_seq_cst
|
||||
fLayout.store(layout);
|
||||
|
@ -785,6 +785,48 @@ GrBackendTexture GrContext::createCompressedBackendTexture(int width, int height
|
||||
finishedContext);
|
||||
}
|
||||
|
||||
bool GrContext::setBackendTextureState(const GrBackendTexture& backendTexture,
|
||||
const GrBackendSurfaceMutableState& state,
|
||||
GrGpuFinishedProc finishedProc,
|
||||
GrGpuFinishedContext finishedContext) {
|
||||
if (!this->asDirectContext()) {
|
||||
finishedProc(finishedContext);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this->abandoned()) {
|
||||
finishedProc(finishedContext);
|
||||
return false;
|
||||
}
|
||||
|
||||
sk_sp<GrRefCntedCallback> callback;
|
||||
if (finishedProc) {
|
||||
callback.reset(new GrRefCntedCallback(finishedProc, finishedContext));
|
||||
}
|
||||
return fGpu->setBackendTextureState(backendTexture, state, std::move(callback));
|
||||
}
|
||||
|
||||
bool GrContext::setBackendRenderTargetState(const GrBackendRenderTarget& backendRenderTarget,
|
||||
const GrBackendSurfaceMutableState& state,
|
||||
GrGpuFinishedProc finishedProc,
|
||||
GrGpuFinishedContext finishedContext) {
|
||||
if (!this->asDirectContext()) {
|
||||
finishedProc(finishedContext);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this->abandoned()) {
|
||||
finishedProc(finishedContext);
|
||||
return false;
|
||||
}
|
||||
|
||||
sk_sp<GrRefCntedCallback> callback;
|
||||
if (finishedProc) {
|
||||
callback.reset(new GrRefCntedCallback(finishedProc, finishedContext));
|
||||
}
|
||||
return fGpu->setBackendRenderTargetState(backendRenderTarget, state, std::move(callback));
|
||||
}
|
||||
|
||||
void GrContext::deleteBackendTexture(GrBackendTexture backendTex) {
|
||||
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
|
||||
// For the Vulkan backend we still must destroy the backend texture when the context is
|
||||
@ -796,6 +838,8 @@ void GrContext::deleteBackendTexture(GrBackendTexture backendTex) {
|
||||
fGpu->deleteBackendTexture(backendTex);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool GrContext::precompileShader(const SkData& key, const SkData& data) {
|
||||
return fGpu->precompileShader(key, data);
|
||||
}
|
||||
|
@ -622,6 +622,18 @@ public:
|
||||
GrGpuFinishedContext finishedContext,
|
||||
const BackendTextureData*);
|
||||
|
||||
virtual bool setBackendTextureState(const GrBackendTexture&,
|
||||
const GrBackendSurfaceMutableState&,
|
||||
sk_sp<GrRefCntedCallback> finishedCallback) {
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool setBackendRenderTargetState(const GrBackendRenderTarget&,
|
||||
const GrBackendSurfaceMutableState&,
|
||||
sk_sp<GrRefCntedCallback> finishedCallback) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees a texture created by createBackendTexture(). If ownership of the backend
|
||||
* texture has been transferred to a GrContext using adopt semantics this should not be called.
|
||||
|
@ -1778,6 +1778,51 @@ GrBackendTexture GrVkGpu::onCreateCompressedBackendTexture(
|
||||
return beTex;
|
||||
}
|
||||
|
||||
bool GrVkGpu::setBackendSurfaceState(GrVkImageInfo info,
|
||||
sk_sp<GrBackendSurfaceMutableStateImpl> currentState,
|
||||
SkISize dimensions,
|
||||
const GrVkSharedImageInfo& newInfo) {
|
||||
sk_sp<GrVkTexture> texture = GrVkTexture::MakeWrappedTexture(
|
||||
this, dimensions, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, kRW_GrIOType, info,
|
||||
std::move(currentState));
|
||||
SkASSERT(texture);
|
||||
if (!texture) {
|
||||
return false;
|
||||
}
|
||||
// Even though internally we use this helper for getting src access flags and stages they
|
||||
// can also be used for general dst flags since we don't know exactly what the client
|
||||
// plans on using the image for.
|
||||
VkImageLayout newLayout = newInfo.getImageLayout();
|
||||
VkPipelineStageFlags dstStage = GrVkImage::LayoutToPipelineSrcStageFlags(newLayout);
|
||||
VkAccessFlags dstAccess = GrVkImage::LayoutToSrcAccessMask(newLayout);
|
||||
texture->setImageLayoutAndQueueIndex(this, newLayout, dstAccess, dstStage, false,
|
||||
newInfo.getQueueFamilyIndex());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GrVkGpu::setBackendTextureState(const GrBackendTexture& backendTeture,
|
||||
const GrBackendSurfaceMutableState& newState,
|
||||
sk_sp<GrRefCntedCallback> finishedCallback) {
|
||||
GrVkImageInfo info;
|
||||
SkAssertResult(backendTeture.getVkImageInfo(&info));
|
||||
sk_sp<GrBackendSurfaceMutableStateImpl> currentState = backendTeture.getMutableState();
|
||||
SkASSERT(currentState);
|
||||
SkASSERT(newState.fBackend == GrBackend::kVulkan);
|
||||
return this->setBackendSurfaceState(info, std::move(currentState), backendTeture.dimensions(),
|
||||
newState.fVkState);
|
||||
}
|
||||
|
||||
bool GrVkGpu::setBackendRenderTargetState(const GrBackendRenderTarget& backendRenderTarget,
|
||||
const GrBackendSurfaceMutableState& newState,
|
||||
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);
|
||||
}
|
||||
|
||||
void GrVkGpu::querySampleLocations(GrRenderTarget* renderTarget,
|
||||
SkTArray<SkPoint>* sampleLocations) {
|
||||
@ -1944,7 +1989,9 @@ void GrVkGpu::addImageMemoryBarrier(const GrManagedResource* resource,
|
||||
}
|
||||
|
||||
void GrVkGpu::prepareSurfacesForBackendAccessAndExternalIO(
|
||||
GrSurfaceProxy* proxies[], int numProxies, SkSurface::BackendSurfaceAccess access,
|
||||
GrSurfaceProxy* proxies[],
|
||||
int numProxies,
|
||||
SkSurface::BackendSurfaceAccess access,
|
||||
const GrPrepareForExternalIORequests& externalRequests) {
|
||||
SkASSERT(numProxies >= 0);
|
||||
SkASSERT(!numProxies || proxies);
|
||||
|
@ -73,6 +73,14 @@ public:
|
||||
|
||||
void xferBarrier(GrRenderTarget*, GrXferBarrierType) override {}
|
||||
|
||||
bool setBackendTextureState(const GrBackendTexture&,
|
||||
const GrBackendSurfaceMutableState&,
|
||||
sk_sp<GrRefCntedCallback> finishedCallback) override;
|
||||
|
||||
bool setBackendRenderTargetState(const GrBackendRenderTarget&,
|
||||
const GrBackendSurfaceMutableState&,
|
||||
sk_sp<GrRefCntedCallback> finishedCallback) override;
|
||||
|
||||
void deleteBackendTexture(const GrBackendTexture&) override;
|
||||
|
||||
bool compile(const GrProgramDesc&, const GrProgramInfo&) override;
|
||||
@ -193,6 +201,11 @@ private:
|
||||
sk_sp<GrRefCntedCallback> finishedCallback,
|
||||
const BackendTextureData*) override;
|
||||
|
||||
bool setBackendSurfaceState(GrVkImageInfo info,
|
||||
sk_sp<GrBackendSurfaceMutableStateImpl> currentState,
|
||||
SkISize dimensions,
|
||||
const GrVkSharedImageInfo& newInfo);
|
||||
|
||||
sk_sp<GrTexture> onCreateTexture(SkISize,
|
||||
const GrBackendFormat&,
|
||||
GrRenderable,
|
||||
|
@ -9,13 +9,14 @@
|
||||
#include "include/gpu/GrBackendSurface.h"
|
||||
#include "include/gpu/GrContext.h"
|
||||
#include "include/gpu/vk/GrVkTypes.h"
|
||||
#include "src/gpu/GrContextPriv.h"
|
||||
#include "src/gpu/GrTexture.h"
|
||||
#include "src/gpu/GrTextureProxy.h"
|
||||
#include "src/image/SkImage_Base.h"
|
||||
#include "tests/Test.h"
|
||||
|
||||
#ifdef SK_VULKAN
|
||||
|
||||
#include "src/gpu/vk/GrVkGpu.h"
|
||||
#include "src/gpu/vk/GrVkTexture.h"
|
||||
|
||||
DEF_GPUTEST_FOR_VULKAN_CONTEXT(VkBackendSurfaceMutableStateTest, reporter, ctxInfo) {
|
||||
@ -102,6 +103,41 @@ DEF_GPUTEST_FOR_VULKAN_CONTEXT(VkBackendSurfaceMutableStateTest, reporter, ctxIn
|
||||
REPORTER_ASSERT(reporter, initLayout == info.fImageLayout);
|
||||
REPORTER_ASSERT(reporter, initQueue == info.fCurrentQueueFamily);
|
||||
|
||||
// Test using the setBackendTextureStateAPI. Unlike the previous test this will actually add
|
||||
// real transitions to the image so we need to be careful about doing actual valid transitions.
|
||||
GrVkGpu* gpu = static_cast<GrVkGpu*>(context->priv().getGpu());
|
||||
|
||||
context->setBackendTextureState(backendTex, newState);
|
||||
|
||||
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);
|
||||
|
||||
// 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);
|
||||
|
||||
context->setBackendTextureState(backendTex, externalState);
|
||||
|
||||
REPORTER_ASSERT(reporter, backendTex.getVkImageInfo(&info));
|
||||
REPORTER_ASSERT(reporter, VK_IMAGE_LAYOUT_GENERAL == info.fImageLayout);
|
||||
REPORTER_ASSERT(reporter, VK_QUEUE_FAMILY_EXTERNAL == info.fCurrentQueueFamily);
|
||||
|
||||
context->submit();
|
||||
|
||||
GrBackendSurfaceMutableState externalState2(VK_IMAGE_LAYOUT_GENERAL, initQueue);
|
||||
context->setBackendTextureState(backendTex, externalState2);
|
||||
|
||||
REPORTER_ASSERT(reporter, backendTex.getVkImageInfo(&info));
|
||||
REPORTER_ASSERT(reporter, VK_IMAGE_LAYOUT_GENERAL == info.fImageLayout);
|
||||
REPORTER_ASSERT(reporter, gpu->queueIndex() == info.fCurrentQueueFamily);
|
||||
}
|
||||
|
||||
// We must submit this work before we try to delete the backend texture.
|
||||
context->submit(true);
|
||||
|
||||
context->deleteBackendTexture(backendTex);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user