Make non-ddl lazy proxys clean-up and delete their callbacks immediately after instanstation.

This makes sure resources are released and free'd as soon as possible if we
no longer need them.

Bug: skia:
Change-Id: Ic216987649c54183f8cbbff90a633860a97754b3
Reviewed-on: https://skia-review.googlesource.com/105721
Commit-Queue: Greg Daniel <egdaniel@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Greg Daniel 2018-02-08 15:05:44 -05:00 committed by Skia Commit-Bot
parent 5635631c88
commit 457469c7a0
12 changed files with 100 additions and 47 deletions

View File

@ -77,8 +77,8 @@ protected:
//
// The minimal knowledge version is used for CCPR where we are generating an atlas but we do not
// know the final size until flush time.
GrRenderTargetProxy(LazyInstantiateCallback&&, const GrSurfaceDesc&, SkBackingFit, SkBudgeted,
uint32_t flags);
GrRenderTargetProxy(LazyInstantiateCallback&&, LazyInstantiationType lazyType,
const GrSurfaceDesc&, SkBackingFit, SkBudgeted, uint32_t flags);
// Wrapped version
GrRenderTargetProxy(sk_sp<GrSurface>, GrSurfaceOrigin);

View File

@ -182,6 +182,11 @@ private:
class GrSurfaceProxy : public GrIORefProxy {
public:
enum class LazyInstantiationType {
kSingleUse, // Instantiation callback is allowed to be called only once
kMultipleUse, // Instantiation callback can be called multiple times.
};
enum class LazyState {
kNot, // The proxy is instantiated or does not have a lazy callback
kPartially, // The proxy has a lazy callback but knows basic information about itself.
@ -351,7 +356,8 @@ public:
protected:
// Deferred version
GrSurfaceProxy(const GrSurfaceDesc& desc, SkBackingFit fit, SkBudgeted budgeted, uint32_t flags)
: GrSurfaceProxy(nullptr, desc, fit, budgeted, flags) {
: GrSurfaceProxy(nullptr, LazyInstantiationType::kSingleUse,
desc, fit, budgeted, flags) {
// Note: this ctor pulls a new uniqueID from the same pool at the GrGpuResources
}
@ -359,8 +365,9 @@ protected:
GrSurfaceOrigin* outOrigin)>;
// Lazy-callback version
GrSurfaceProxy(LazyInstantiateCallback&& callback, const GrSurfaceDesc& desc,
SkBackingFit fit, SkBudgeted budgeted, uint32_t flags);
GrSurfaceProxy(LazyInstantiateCallback&& callback, LazyInstantiationType lazyType,
const GrSurfaceDesc& desc, SkBackingFit fit, SkBudgeted budgeted,
uint32_t flags);
// Wrapped version
GrSurfaceProxy(sk_sp<GrSurface> surface, GrSurfaceOrigin origin, SkBackingFit fit);
@ -408,6 +415,12 @@ private:
const UniqueID fUniqueID; // set from the backing resource for wrapped resources
LazyInstantiateCallback fLazyInstantiateCallback;
// If this is set to kSingleuse, then after one call to fLazyInstantiateCallback we will cleanup
// the lazy callback and then delete it. This will allow for any refs and resources being held
// by the standard function to be released. This is specifically useful in non-dll cases where
// we make lazy proxies and instantiate them immediately.
// Note: This is ignored if fLazyInstantiateCallback is null.
LazyInstantiationType fLazyInstantiationType;
SkDEBUGCODE(virtual void validateLazySurface(const GrSurface*) = 0;)
static const size_t kInvalidGpuMemorySize = ~static_cast<size_t>(0);

View File

@ -80,8 +80,8 @@ protected:
//
// The minimal knowledge version is used for CCPR where we are generating an atlas but we do not
// know the final size until flush time.
GrTextureProxy(LazyInstantiateCallback&&, const GrSurfaceDesc& desc, GrMipMapped,
SkBackingFit fit, SkBudgeted budgeted, uint32_t flags);
GrTextureProxy(LazyInstantiateCallback&&, LazyInstantiationType, const GrSurfaceDesc& desc,
GrMipMapped, SkBackingFit fit, SkBudgeted budgeted, uint32_t flags);
// Wrapped version
GrTextureProxy(sk_sp<GrSurface>, GrSurfaceOrigin);

View File

@ -537,11 +537,17 @@ sk_sp<GrTextureProxy> GrProxyProvider::createLazyProxy(LazyInstantiateCallback&&
SkASSERT((desc.fWidth <= 0 && desc.fHeight <= 0) ||
(desc.fWidth > 0 && desc.fHeight > 0));
uint32_t flags = GrResourceProvider::kNoPendingIO_Flag;
using LazyInstantiationType = GrSurfaceProxy::LazyInstantiationType;
// For non-ddl draws always make lazy proxy's single use.
LazyInstantiationType lazyType = fResourceProvider ? LazyInstantiationType::kSingleUse
: LazyInstantiationType::kMultipleUse;
return sk_sp<GrTextureProxy>(SkToBool(kRenderTarget_GrSurfaceFlag & desc.fFlags) ?
new GrTextureRenderTargetProxy(std::move(callback), desc,
new GrTextureRenderTargetProxy(std::move(callback), lazyType, desc,
mipMapped, fit, budgeted, flags) :
new GrTextureProxy(std::move(callback), desc, mipMapped, fit,
budgeted, flags));
new GrTextureProxy(std::move(callback), lazyType, desc, mipMapped,
fit, budgeted, flags));
}
sk_sp<GrRenderTargetProxy> GrProxyProvider::createLazyRenderTargetProxy(
@ -553,13 +559,19 @@ sk_sp<GrRenderTargetProxy> GrProxyProvider::createLazyRenderTargetProxy(
SkASSERT((desc.fWidth <= 0 && desc.fHeight <= 0) ||
(desc.fWidth > 0 && desc.fHeight > 0));
uint32_t flags = GrResourceProvider::kNoPendingIO_Flag;
using LazyInstantiationType = GrSurfaceProxy::LazyInstantiationType;
// For non-ddl draws always make lazy proxy's single use.
LazyInstantiationType lazyType = fResourceProvider ? LazyInstantiationType::kSingleUse
: LazyInstantiationType::kMultipleUse;
if (Textureable::kYes == textureable) {
return sk_sp<GrRenderTargetProxy>(new GrTextureRenderTargetProxy(std::move(callback), desc,
mipMapped, fit, budgeted,
flags));
return sk_sp<GrRenderTargetProxy>(new GrTextureRenderTargetProxy(std::move(callback),
lazyType, desc, mipMapped,
fit, budgeted, flags));
}
return sk_sp<GrRenderTargetProxy>(new GrRenderTargetProxy(std::move(callback), desc,
return sk_sp<GrRenderTargetProxy>(new GrRenderTargetProxy(std::move(callback), lazyType, desc,
fit, budgeted, flags));
}

View File

@ -156,7 +156,6 @@ public:
using LazyInstantiateCallback = std::function<sk_sp<GrSurface>(GrResourceProvider*,
GrSurfaceOrigin* outOrigin)>;
enum class Textureable : bool {
kNo = false,
kYes = true

View File

@ -36,10 +36,11 @@ GrRenderTargetProxy::GrRenderTargetProxy(const GrCaps& caps, const GrSurfaceDesc
// Lazy-callback version
GrRenderTargetProxy::GrRenderTargetProxy(LazyInstantiateCallback&& callback,
LazyInstantiationType lazyType,
const GrSurfaceDesc& desc,
SkBackingFit fit, SkBudgeted budgeted,
uint32_t flags)
: INHERITED(std::move(callback), desc, fit, budgeted, flags)
: INHERITED(std::move(callback), lazyType, desc, fit, budgeted, flags)
, fSampleCnt(desc.fSampleCnt)
, fNeedsStencil(false)
, fRenderTargetFlags(GrRenderTargetFlags::kNone) {

View File

@ -44,8 +44,9 @@ static bool is_valid_non_lazy(const GrSurfaceDesc& desc) {
#endif
// Lazy-callback version
GrSurfaceProxy::GrSurfaceProxy(LazyInstantiateCallback&& callback, const GrSurfaceDesc& desc,
SkBackingFit fit, SkBudgeted budgeted, uint32_t flags)
GrSurfaceProxy::GrSurfaceProxy(LazyInstantiateCallback&& callback, LazyInstantiationType lazyType,
const GrSurfaceDesc& desc, SkBackingFit fit, SkBudgeted budgeted,
uint32_t flags)
: fConfig(desc.fConfig)
, fWidth(desc.fWidth)
, fHeight(desc.fHeight)
@ -54,6 +55,7 @@ GrSurfaceProxy::GrSurfaceProxy(LazyInstantiateCallback&& callback, const GrSurfa
, fBudgeted(budgeted)
, fFlags(flags)
, fLazyInstantiateCallback(std::move(callback))
, fLazyInstantiationType(lazyType)
, fNeedsClear(SkToBool(desc.fFlags & kPerformInitialClear_GrSurfaceFlag))
, fGpuMemorySize(kInvalidGpuMemorySize)
, fLastOpList(nullptr) {
@ -63,7 +65,6 @@ GrSurfaceProxy::GrSurfaceProxy(LazyInstantiateCallback&& callback, const GrSurfa
} else {
SkASSERT(is_valid_non_lazy(desc));
}
}
// Wrapped version
@ -361,6 +362,10 @@ bool GrSurfaceProxyPriv::doLazyInstantiation(GrResourceProvider* resourceProvide
}
sk_sp<GrSurface> surface = fProxy->fLazyInstantiateCallback(resourceProvider, outOrigin);
if (GrSurfaceProxy::LazyInstantiationType::kSingleUse == fProxy->fLazyInstantiationType) {
fProxy->fLazyInstantiateCallback(nullptr, nullptr);
fProxy->fLazyInstantiateCallback = nullptr;
}
if (!surface) {
fProxy->fWidth = 0;
fProxy->fHeight = 0;

View File

@ -70,6 +70,14 @@ public:
bool doLazyInstantiation(GrResourceProvider*);
GrSurfaceProxy::LazyInstantiationType lazyInstantiationType() const {
return fProxy->fLazyInstantiationType;
}
void testingOnly_setLazyInstantiationType(GrSurfaceProxy::LazyInstantiationType lazyType) {
fProxy->fLazyInstantiationType = lazyType;
}
static bool AttachStencilIfNeeded(GrResourceProvider*, GrSurface*, bool needsStencil);
private:

View File

@ -26,10 +26,10 @@ GrTextureProxy::GrTextureProxy(const GrSurfaceDesc& srcDesc, SkBackingFit fit, S
}
// Lazy-callback version
GrTextureProxy::GrTextureProxy(LazyInstantiateCallback&& callback, const GrSurfaceDesc& desc,
GrMipMapped mipMapped, SkBackingFit fit, SkBudgeted budgeted,
uint32_t flags)
: INHERITED(std::move(callback), desc, fit, budgeted, flags)
GrTextureProxy::GrTextureProxy(LazyInstantiateCallback&& callback, LazyInstantiationType lazyType,
const GrSurfaceDesc& desc, GrMipMapped mipMapped, SkBackingFit fit,
SkBudgeted budgeted, uint32_t flags)
: INHERITED(std::move(callback), lazyType, desc, fit, budgeted, flags)
, fMipMapped(mipMapped)
, fMipColorMode(SkDestinationSurfaceColorMode::kLegacy)
, fProxyProvider(nullptr)

View File

@ -29,16 +29,17 @@ GrTextureRenderTargetProxy::GrTextureRenderTargetProxy(const GrCaps& caps,
// Lazy-callback version
GrTextureRenderTargetProxy::GrTextureRenderTargetProxy(LazyInstantiateCallback&& callback,
LazyInstantiationType lazyType,
const GrSurfaceDesc& desc,
GrMipMapped mipMapped,
SkBackingFit fit,
SkBudgeted budgeted,
uint32_t flags)
: GrSurfaceProxy(std::move(callback), desc, fit, budgeted, flags)
: GrSurfaceProxy(std::move(callback), lazyType, desc, fit, budgeted, flags)
// Since we have virtual inheritance, we initialize GrSurfaceProxy directly. Send null
// callbacks to the texture and RT proxies simply to route to the appropriate constructors.
, GrTextureProxy(LazyInstantiateCallback(), desc, mipMapped, fit, budgeted, flags)
, GrRenderTargetProxy(LazyInstantiateCallback(), desc, fit, budgeted, flags) {
, GrTextureProxy(LazyInstantiateCallback(), lazyType, desc, mipMapped, fit, budgeted, flags)
, GrRenderTargetProxy(LazyInstantiateCallback(), lazyType, desc, fit, budgeted, flags) {
}
// Wrapped version

View File

@ -32,8 +32,9 @@ private:
SkBackingFit, SkBudgeted, uint32_t flags);
// Lazy-callback version
GrTextureRenderTargetProxy(LazyInstantiateCallback&&, const GrSurfaceDesc& desc, GrMipMapped,
SkBackingFit, SkBudgeted, uint32_t flags);
GrTextureRenderTargetProxy(LazyInstantiateCallback&&, LazyInstantiationType,
const GrSurfaceDesc& desc, GrMipMapped, SkBackingFit, SkBudgeted,
uint32_t flags);
// Wrapped version
GrTextureRenderTargetProxy(sk_sp<GrSurface>, GrSurfaceOrigin);

View File

@ -213,29 +213,42 @@ DEF_GPUTEST(LazyProxyReleaseTest, reporter, /* options */) {
desc.fHeight = kSize;
desc.fConfig = kRGBA_8888_GrPixelConfig;
using LazyInstantiationType = GrSurfaceProxy::LazyInstantiationType;
for (bool doInstantiate : {true, false}) {
int testCount = 0;
int* testCountPtr = &testCount;
sk_sp<GrTextureProxy> proxy = proxyProvider->createLazyProxy(
[testCountPtr](GrResourceProvider* resourceProvider, GrSurfaceOrigin* outOrigin) {
if (!resourceProvider) {
*testCountPtr = -1;
for (auto lazyType : {LazyInstantiationType::kSingleUse,
LazyInstantiationType::kMultipleUse}) {
int testCount = 0;
int* testCountPtr = &testCount;
sk_sp<GrTextureProxy> proxy = proxyProvider->createLazyProxy(
[testCountPtr](GrResourceProvider* resourceProvider,
GrSurfaceOrigin* /*outOrigin*/) {
if (!resourceProvider) {
*testCountPtr = -1;
return sk_sp<GrTexture>();
}
*testCountPtr = 1;
return sk_sp<GrTexture>();
}
*testCountPtr = 1;
return sk_sp<GrTexture>();
}, desc, GrMipMapped::kNo, SkBackingFit::kExact, SkBudgeted::kNo);
}, desc, GrMipMapped::kNo, SkBackingFit::kExact, SkBudgeted::kNo);
REPORTER_ASSERT(reporter, 0 == testCount);
proxy->priv().testingOnly_setLazyInstantiationType(lazyType);
if (doInstantiate) {
proxy->priv().doLazyInstantiation(ctx->contextPriv().resourceProvider());
REPORTER_ASSERT(reporter, 1 == testCount);
proxy.reset();
REPORTER_ASSERT(reporter, -1 == testCount);
} else {
proxy.reset();
REPORTER_ASSERT(reporter, -1 == testCount);
REPORTER_ASSERT(reporter, 0 == testCount);
if (doInstantiate) {
proxy->priv().doLazyInstantiation(ctx->contextPriv().resourceProvider());
if (LazyInstantiationType::kSingleUse == proxy->priv().lazyInstantiationType()) {
// In SingleUse we will call the cleanup and delete the callback in the
// doLazyInstantiationCall.
REPORTER_ASSERT(reporter, -1 == testCount);
} else {
REPORTER_ASSERT(reporter, 1 == testCount);
}
proxy.reset();
REPORTER_ASSERT(reporter, -1 == testCount);
} else {
proxy.reset();
REPORTER_ASSERT(reporter, -1 == testCount);
}
}
}
}