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
@ -9,6 +9,10 @@ Milestone 85
|
|||||||
|
|
||||||
* <insert new release notes here>
|
* <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
|
* 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.
|
also calls the release proc on failure.
|
||||||
|
@ -51,6 +51,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
friend class GrBackendSurfaceMutableStateImpl;
|
friend class GrBackendSurfaceMutableStateImpl;
|
||||||
|
friend class GrVkGpu;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
char fDummy;
|
char fDummy;
|
||||||
|
@ -665,6 +665,26 @@ public:
|
|||||||
GrGpuFinishedProc finishedProc = nullptr,
|
GrGpuFinishedProc finishedProc = nullptr,
|
||||||
GrGpuFinishedContext finishedContext = 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);
|
void deleteBackendTexture(GrBackendTexture);
|
||||||
|
|
||||||
// This interface allows clients to pre-compile shaders and populate the runtime program cache.
|
// This interface allows clients to pre-compile shaders and populate the runtime program cache.
|
||||||
|
@ -53,7 +53,6 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void setImageLayout(VkImageLayout layout) {
|
void setImageLayout(VkImageLayout layout) {
|
||||||
// Defaulting to use std::memory_order_seq_cst
|
// Defaulting to use std::memory_order_seq_cst
|
||||||
fLayout.store(layout);
|
fLayout.store(layout);
|
||||||
|
@ -785,6 +785,48 @@ GrBackendTexture GrContext::createCompressedBackendTexture(int width, int height
|
|||||||
finishedContext);
|
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) {
|
void GrContext::deleteBackendTexture(GrBackendTexture backendTex) {
|
||||||
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
|
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
|
||||||
// For the Vulkan backend we still must destroy the backend texture when the context is
|
// 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);
|
fGpu->deleteBackendTexture(backendTex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
bool GrContext::precompileShader(const SkData& key, const SkData& data) {
|
bool GrContext::precompileShader(const SkData& key, const SkData& data) {
|
||||||
return fGpu->precompileShader(key, data);
|
return fGpu->precompileShader(key, data);
|
||||||
}
|
}
|
||||||
|
@ -622,6 +622,18 @@ public:
|
|||||||
GrGpuFinishedContext finishedContext,
|
GrGpuFinishedContext finishedContext,
|
||||||
const BackendTextureData*);
|
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
|
* 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.
|
* texture has been transferred to a GrContext using adopt semantics this should not be called.
|
||||||
|
@ -1778,6 +1778,51 @@ GrBackendTexture GrVkGpu::onCreateCompressedBackendTexture(
|
|||||||
return beTex;
|
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,
|
void GrVkGpu::querySampleLocations(GrRenderTarget* renderTarget,
|
||||||
SkTArray<SkPoint>* sampleLocations) {
|
SkTArray<SkPoint>* sampleLocations) {
|
||||||
@ -1944,7 +1989,9 @@ void GrVkGpu::addImageMemoryBarrier(const GrManagedResource* resource,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GrVkGpu::prepareSurfacesForBackendAccessAndExternalIO(
|
void GrVkGpu::prepareSurfacesForBackendAccessAndExternalIO(
|
||||||
GrSurfaceProxy* proxies[], int numProxies, SkSurface::BackendSurfaceAccess access,
|
GrSurfaceProxy* proxies[],
|
||||||
|
int numProxies,
|
||||||
|
SkSurface::BackendSurfaceAccess access,
|
||||||
const GrPrepareForExternalIORequests& externalRequests) {
|
const GrPrepareForExternalIORequests& externalRequests) {
|
||||||
SkASSERT(numProxies >= 0);
|
SkASSERT(numProxies >= 0);
|
||||||
SkASSERT(!numProxies || proxies);
|
SkASSERT(!numProxies || proxies);
|
||||||
|
@ -73,6 +73,14 @@ public:
|
|||||||
|
|
||||||
void xferBarrier(GrRenderTarget*, GrXferBarrierType) override {}
|
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;
|
void deleteBackendTexture(const GrBackendTexture&) override;
|
||||||
|
|
||||||
bool compile(const GrProgramDesc&, const GrProgramInfo&) override;
|
bool compile(const GrProgramDesc&, const GrProgramInfo&) override;
|
||||||
@ -193,6 +201,11 @@ private:
|
|||||||
sk_sp<GrRefCntedCallback> finishedCallback,
|
sk_sp<GrRefCntedCallback> finishedCallback,
|
||||||
const BackendTextureData*) override;
|
const BackendTextureData*) override;
|
||||||
|
|
||||||
|
bool setBackendSurfaceState(GrVkImageInfo info,
|
||||||
|
sk_sp<GrBackendSurfaceMutableStateImpl> currentState,
|
||||||
|
SkISize dimensions,
|
||||||
|
const GrVkSharedImageInfo& newInfo);
|
||||||
|
|
||||||
sk_sp<GrTexture> onCreateTexture(SkISize,
|
sk_sp<GrTexture> onCreateTexture(SkISize,
|
||||||
const GrBackendFormat&,
|
const GrBackendFormat&,
|
||||||
GrRenderable,
|
GrRenderable,
|
||||||
|
@ -9,13 +9,14 @@
|
|||||||
#include "include/gpu/GrBackendSurface.h"
|
#include "include/gpu/GrBackendSurface.h"
|
||||||
#include "include/gpu/GrContext.h"
|
#include "include/gpu/GrContext.h"
|
||||||
#include "include/gpu/vk/GrVkTypes.h"
|
#include "include/gpu/vk/GrVkTypes.h"
|
||||||
|
#include "src/gpu/GrContextPriv.h"
|
||||||
#include "src/gpu/GrTexture.h"
|
#include "src/gpu/GrTexture.h"
|
||||||
#include "src/gpu/GrTextureProxy.h"
|
#include "src/gpu/GrTextureProxy.h"
|
||||||
#include "src/image/SkImage_Base.h"
|
#include "src/image/SkImage_Base.h"
|
||||||
#include "tests/Test.h"
|
#include "tests/Test.h"
|
||||||
|
|
||||||
#ifdef SK_VULKAN
|
#ifdef SK_VULKAN
|
||||||
|
#include "src/gpu/vk/GrVkGpu.h"
|
||||||
#include "src/gpu/vk/GrVkTexture.h"
|
#include "src/gpu/vk/GrVkTexture.h"
|
||||||
|
|
||||||
DEF_GPUTEST_FOR_VULKAN_CONTEXT(VkBackendSurfaceMutableStateTest, reporter, ctxInfo) {
|
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, initLayout == info.fImageLayout);
|
||||||
REPORTER_ASSERT(reporter, initQueue == info.fCurrentQueueFamily);
|
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);
|
context->deleteBackendTexture(backendTex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user