1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2017 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h" 9cb93a386Sopenharmony_ci#include "include/core/SkSpan.h" 10cb93a386Sopenharmony_ci#include "include/core/SkSurface.h" 11cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h" 12cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h" 13cb93a386Sopenharmony_ci#include "src/gpu/GrGpu.h" 14cb93a386Sopenharmony_ci#include "src/gpu/GrProxyProvider.h" 15cb93a386Sopenharmony_ci#include "src/gpu/GrResourceAllocator.h" 16cb93a386Sopenharmony_ci#include "src/gpu/GrResourceProviderPriv.h" 17cb93a386Sopenharmony_ci#include "src/gpu/GrSurfaceProxyPriv.h" 18cb93a386Sopenharmony_ci#include "src/gpu/GrTexture.h" 19cb93a386Sopenharmony_ci#include "src/gpu/GrTextureProxy.h" 20cb93a386Sopenharmony_ci#include "tests/Test.h" 21cb93a386Sopenharmony_ci#include "tools/gpu/ManagedBackendTexture.h" 22cb93a386Sopenharmony_ci 23cb93a386Sopenharmony_cinamespace { 24cb93a386Sopenharmony_cistruct ProxyParams { 25cb93a386Sopenharmony_ci int fSize; 26cb93a386Sopenharmony_ci GrRenderable fRenderable; 27cb93a386Sopenharmony_ci GrColorType fColorType; 28cb93a386Sopenharmony_ci SkBackingFit fFit; 29cb93a386Sopenharmony_ci int fSampleCnt; 30cb93a386Sopenharmony_ci SkBudgeted fBudgeted; 31cb93a386Sopenharmony_ci enum Kind { 32cb93a386Sopenharmony_ci kDeferred, 33cb93a386Sopenharmony_ci kBackend, 34cb93a386Sopenharmony_ci kFullyLazy, 35cb93a386Sopenharmony_ci kLazy, 36cb93a386Sopenharmony_ci kInstantiated 37cb93a386Sopenharmony_ci }; 38cb93a386Sopenharmony_ci Kind fKind; 39cb93a386Sopenharmony_ci GrUniqueKey fUniqueKey = GrUniqueKey(); 40cb93a386Sopenharmony_ci // TODO: do we care about mipmapping 41cb93a386Sopenharmony_ci}; 42cb93a386Sopenharmony_ci 43cb93a386Sopenharmony_ciconstexpr GrRenderable kRT = GrRenderable::kYes; 44cb93a386Sopenharmony_ciconstexpr GrRenderable kNotRT = GrRenderable::kNo; 45cb93a386Sopenharmony_ci 46cb93a386Sopenharmony_ciconstexpr GrColorType kRGBA = GrColorType::kRGBA_8888; 47cb93a386Sopenharmony_ciconstexpr GrColorType kAlpha = GrColorType::kAlpha_8; 48cb93a386Sopenharmony_ci 49cb93a386Sopenharmony_ciconstexpr SkBackingFit kE = SkBackingFit::kExact; 50cb93a386Sopenharmony_ciconstexpr SkBackingFit kA = SkBackingFit::kApprox; 51cb93a386Sopenharmony_ci 52cb93a386Sopenharmony_ciconstexpr SkBudgeted kNotB = SkBudgeted::kNo; 53cb93a386Sopenharmony_ciconstexpr SkBudgeted kB = SkBudgeted::kYes; 54cb93a386Sopenharmony_ci 55cb93a386Sopenharmony_ciconstexpr ProxyParams::Kind kDeferred = ProxyParams::Kind::kDeferred; 56cb93a386Sopenharmony_ciconstexpr ProxyParams::Kind kBackend = ProxyParams::Kind::kBackend; 57cb93a386Sopenharmony_ciconstexpr ProxyParams::Kind kInstantiated = ProxyParams::Kind::kInstantiated; 58cb93a386Sopenharmony_ciconstexpr ProxyParams::Kind kLazy = ProxyParams::Kind::kLazy; 59cb93a386Sopenharmony_ciconstexpr ProxyParams::Kind kFullyLazy = ProxyParams::Kind::kFullyLazy; 60cb93a386Sopenharmony_ci}; 61cb93a386Sopenharmony_ci 62cb93a386Sopenharmony_cistatic sk_sp<GrSurfaceProxy> make_deferred(GrProxyProvider* proxyProvider, const GrCaps* caps, 63cb93a386Sopenharmony_ci const ProxyParams& p) { 64cb93a386Sopenharmony_ci const GrBackendFormat format = caps->getDefaultBackendFormat(p.fColorType, p.fRenderable); 65cb93a386Sopenharmony_ci return proxyProvider->createProxy(format, {p.fSize, p.fSize}, p.fRenderable, p.fSampleCnt, 66cb93a386Sopenharmony_ci GrMipmapped::kNo, p.fFit, p.fBudgeted, GrProtected::kNo); 67cb93a386Sopenharmony_ci} 68cb93a386Sopenharmony_ci 69cb93a386Sopenharmony_cistatic sk_sp<GrSurfaceProxy> make_backend(GrDirectContext* dContext, const ProxyParams& p) { 70cb93a386Sopenharmony_ci GrProxyProvider* proxyProvider = dContext->priv().proxyProvider(); 71cb93a386Sopenharmony_ci 72cb93a386Sopenharmony_ci SkColorType skColorType = GrColorTypeToSkColorType(p.fColorType); 73cb93a386Sopenharmony_ci SkASSERT(SkColorType::kUnknown_SkColorType != skColorType); 74cb93a386Sopenharmony_ci 75cb93a386Sopenharmony_ci auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData( 76cb93a386Sopenharmony_ci dContext, p.fSize, p.fSize, skColorType, GrMipmapped::kNo, GrRenderable::kNo); 77cb93a386Sopenharmony_ci 78cb93a386Sopenharmony_ci if (!mbet) { 79cb93a386Sopenharmony_ci return nullptr; 80cb93a386Sopenharmony_ci } 81cb93a386Sopenharmony_ci 82cb93a386Sopenharmony_ci return proxyProvider->wrapBackendTexture(mbet->texture(), 83cb93a386Sopenharmony_ci kBorrow_GrWrapOwnership, 84cb93a386Sopenharmony_ci GrWrapCacheable::kNo, 85cb93a386Sopenharmony_ci kRead_GrIOType, 86cb93a386Sopenharmony_ci mbet->refCountedCallback()); 87cb93a386Sopenharmony_ci} 88cb93a386Sopenharmony_ci 89cb93a386Sopenharmony_cistatic sk_sp<GrSurfaceProxy> make_fully_lazy(GrProxyProvider* proxyProvider, const GrCaps* caps, 90cb93a386Sopenharmony_ci const ProxyParams& p) { 91cb93a386Sopenharmony_ci const GrBackendFormat format = caps->getDefaultBackendFormat(p.fColorType, p.fRenderable); 92cb93a386Sopenharmony_ci auto cb = [p](GrResourceProvider* provider, const GrSurfaceProxy::LazySurfaceDesc& desc) { 93cb93a386Sopenharmony_ci auto tex = provider->createTexture({p.fSize, p.fSize}, desc.fFormat, 94cb93a386Sopenharmony_ci desc.fTextureType, 95cb93a386Sopenharmony_ci desc.fRenderable, desc.fSampleCnt, 96cb93a386Sopenharmony_ci desc.fMipmapped, desc.fBudgeted, 97cb93a386Sopenharmony_ci desc.fProtected); 98cb93a386Sopenharmony_ci return GrSurfaceProxy::LazyCallbackResult(std::move(tex)); 99cb93a386Sopenharmony_ci }; 100cb93a386Sopenharmony_ci return GrProxyProvider::MakeFullyLazyProxy(std::move(cb), format, p.fRenderable, p.fSampleCnt, 101cb93a386Sopenharmony_ci GrProtected::kNo, *caps, 102cb93a386Sopenharmony_ci GrSurfaceProxy::UseAllocator::kYes); 103cb93a386Sopenharmony_ci} 104cb93a386Sopenharmony_ci 105cb93a386Sopenharmony_cistatic sk_sp<GrSurfaceProxy> make_lazy(GrProxyProvider* proxyProvider, const GrCaps* caps, 106cb93a386Sopenharmony_ci const ProxyParams& p) { 107cb93a386Sopenharmony_ci const GrBackendFormat format = caps->getDefaultBackendFormat(p.fColorType, p.fRenderable); 108cb93a386Sopenharmony_ci auto cb = [](GrResourceProvider* provider, const GrSurfaceProxy::LazySurfaceDesc& desc) { 109cb93a386Sopenharmony_ci auto tex = provider->createTexture(desc.fDimensions, desc.fFormat, 110cb93a386Sopenharmony_ci desc.fTextureType, 111cb93a386Sopenharmony_ci desc.fRenderable, desc.fSampleCnt, 112cb93a386Sopenharmony_ci desc.fMipmapped, desc.fBudgeted, 113cb93a386Sopenharmony_ci desc.fProtected); 114cb93a386Sopenharmony_ci return GrSurfaceProxy::LazyCallbackResult(std::move(tex)); 115cb93a386Sopenharmony_ci }; 116cb93a386Sopenharmony_ci return proxyProvider->createLazyProxy(std::move(cb), format, {p.fSize, p.fSize}, 117cb93a386Sopenharmony_ci GrMipmapped::kNo, GrMipmapStatus::kNotAllocated, 118cb93a386Sopenharmony_ci GrInternalSurfaceFlags::kNone, 119cb93a386Sopenharmony_ci p.fFit, p.fBudgeted, GrProtected::kNo, 120cb93a386Sopenharmony_ci GrSurfaceProxy::UseAllocator::kYes); 121cb93a386Sopenharmony_ci} 122cb93a386Sopenharmony_ci 123cb93a386Sopenharmony_cistatic sk_sp<GrSurfaceProxy> make_proxy(GrDirectContext* dContext, const ProxyParams& p) { 124cb93a386Sopenharmony_ci GrProxyProvider* proxyProvider = dContext->priv().proxyProvider(); 125cb93a386Sopenharmony_ci const GrCaps* caps = dContext->priv().caps(); 126cb93a386Sopenharmony_ci sk_sp<GrSurfaceProxy> proxy; 127cb93a386Sopenharmony_ci switch (p.fKind) { 128cb93a386Sopenharmony_ci case ProxyParams::kDeferred: 129cb93a386Sopenharmony_ci proxy = make_deferred(proxyProvider, caps, p); 130cb93a386Sopenharmony_ci break; 131cb93a386Sopenharmony_ci case ProxyParams::kBackend: 132cb93a386Sopenharmony_ci proxy = make_backend(dContext, p); 133cb93a386Sopenharmony_ci break; 134cb93a386Sopenharmony_ci case ProxyParams::kFullyLazy: 135cb93a386Sopenharmony_ci proxy = make_fully_lazy(proxyProvider, caps, p); 136cb93a386Sopenharmony_ci break; 137cb93a386Sopenharmony_ci case ProxyParams::kLazy: 138cb93a386Sopenharmony_ci proxy = make_lazy(proxyProvider, caps, p); 139cb93a386Sopenharmony_ci break; 140cb93a386Sopenharmony_ci case ProxyParams::kInstantiated: 141cb93a386Sopenharmony_ci proxy = make_deferred(proxyProvider, caps, p); 142cb93a386Sopenharmony_ci if (proxy) { 143cb93a386Sopenharmony_ci auto surf = proxy->priv().createSurface(dContext->priv().resourceProvider()); 144cb93a386Sopenharmony_ci proxy->priv().assign(std::move(surf)); 145cb93a386Sopenharmony_ci } 146cb93a386Sopenharmony_ci break; 147cb93a386Sopenharmony_ci } 148cb93a386Sopenharmony_ci if (proxy && p.fUniqueKey.isValid()) { 149cb93a386Sopenharmony_ci SkASSERT(proxy->asTextureProxy()); 150cb93a386Sopenharmony_ci proxyProvider->assignUniqueKeyToProxy(p.fUniqueKey, proxy->asTextureProxy()); 151cb93a386Sopenharmony_ci } 152cb93a386Sopenharmony_ci return proxy; 153cb93a386Sopenharmony_ci} 154cb93a386Sopenharmony_ci 155cb93a386Sopenharmony_ci// Basic test that two proxies with overlapping intervals and compatible descriptors are 156cb93a386Sopenharmony_ci// assigned different GrSurfaces. 157cb93a386Sopenharmony_cistatic void overlap_test(skiatest::Reporter* reporter, GrDirectContext* dContext, 158cb93a386Sopenharmony_ci sk_sp<GrSurfaceProxy> p1, sk_sp<GrSurfaceProxy> p2, 159cb93a386Sopenharmony_ci bool expectedResult) { 160cb93a386Sopenharmony_ci GrResourceAllocator alloc(dContext); 161cb93a386Sopenharmony_ci 162cb93a386Sopenharmony_ci alloc.addInterval(p1.get(), 0, 4, GrResourceAllocator::ActualUse::kYes); 163cb93a386Sopenharmony_ci alloc.incOps(); 164cb93a386Sopenharmony_ci alloc.addInterval(p2.get(), 1, 2, GrResourceAllocator::ActualUse::kYes); 165cb93a386Sopenharmony_ci alloc.incOps(); 166cb93a386Sopenharmony_ci 167cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, alloc.planAssignment()); 168cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, alloc.makeBudgetHeadroom()); 169cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, alloc.assign()); 170cb93a386Sopenharmony_ci 171cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p1->peekSurface()); 172cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p2->peekSurface()); 173cb93a386Sopenharmony_ci bool doTheBackingStoresMatch = p1->underlyingUniqueID() == p2->underlyingUniqueID(); 174cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, expectedResult == doTheBackingStoresMatch); 175cb93a386Sopenharmony_ci} 176cb93a386Sopenharmony_ci 177cb93a386Sopenharmony_ci// Test various cases when two proxies do not have overlapping intervals. 178cb93a386Sopenharmony_ci// This mainly acts as a test of the ResourceAllocator's free pool. 179cb93a386Sopenharmony_cistatic void non_overlap_test(skiatest::Reporter* reporter, GrDirectContext* dContext, 180cb93a386Sopenharmony_ci sk_sp<GrSurfaceProxy> p1, sk_sp<GrSurfaceProxy> p2, 181cb93a386Sopenharmony_ci bool expectedResult) { 182cb93a386Sopenharmony_ci GrResourceAllocator alloc(dContext); 183cb93a386Sopenharmony_ci 184cb93a386Sopenharmony_ci alloc.incOps(); 185cb93a386Sopenharmony_ci alloc.incOps(); 186cb93a386Sopenharmony_ci alloc.incOps(); 187cb93a386Sopenharmony_ci alloc.incOps(); 188cb93a386Sopenharmony_ci alloc.incOps(); 189cb93a386Sopenharmony_ci alloc.incOps(); 190cb93a386Sopenharmony_ci 191cb93a386Sopenharmony_ci alloc.addInterval(p1.get(), 0, 2, GrResourceAllocator::ActualUse::kYes); 192cb93a386Sopenharmony_ci alloc.addInterval(p2.get(), 3, 5, GrResourceAllocator::ActualUse::kYes); 193cb93a386Sopenharmony_ci 194cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, alloc.planAssignment()); 195cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, alloc.makeBudgetHeadroom()); 196cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, alloc.assign()); 197cb93a386Sopenharmony_ci 198cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p1->peekSurface()); 199cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, p2->peekSurface()); 200cb93a386Sopenharmony_ci bool doTheBackingStoresMatch = p1->underlyingUniqueID() == p2->underlyingUniqueID(); 201cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, expectedResult == doTheBackingStoresMatch); 202cb93a386Sopenharmony_ci} 203cb93a386Sopenharmony_ci 204cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(ResourceAllocatorTest, reporter, ctxInfo) { 205cb93a386Sopenharmony_ci auto dContext = ctxInfo.directContext(); 206cb93a386Sopenharmony_ci const GrCaps* caps = dContext->priv().caps(); 207cb93a386Sopenharmony_ci 208cb93a386Sopenharmony_ci struct TestCase { 209cb93a386Sopenharmony_ci ProxyParams fP1; 210cb93a386Sopenharmony_ci ProxyParams fP2; 211cb93a386Sopenharmony_ci bool fExpectation; 212cb93a386Sopenharmony_ci }; 213cb93a386Sopenharmony_ci 214cb93a386Sopenharmony_ci constexpr bool kShare = true; 215cb93a386Sopenharmony_ci constexpr bool kDontShare = false; 216cb93a386Sopenharmony_ci 217cb93a386Sopenharmony_ci // Non-RT GrSurfaces are never recycled on some platforms. 218cb93a386Sopenharmony_ci bool kConditionallyShare = caps->reuseScratchTextures(); 219cb93a386Sopenharmony_ci 220cb93a386Sopenharmony_ci static const TestCase overlappingTests[] = { 221cb93a386Sopenharmony_ci // Two proxies with overlapping intervals and compatible descriptors should never share 222cb93a386Sopenharmony_ci // RT version 223cb93a386Sopenharmony_ci {{64, kRT, kRGBA, kA, 1, kNotB, kDeferred}, 224cb93a386Sopenharmony_ci {64, kRT, kRGBA, kA, 1, kNotB, kDeferred}, 225cb93a386Sopenharmony_ci kDontShare}, 226cb93a386Sopenharmony_ci // non-RT version 227cb93a386Sopenharmony_ci {{64, kNotRT, kRGBA, kA, 1, kNotB, kDeferred}, 228cb93a386Sopenharmony_ci {64, kNotRT, kRGBA, kA, 1, kNotB, kDeferred}, 229cb93a386Sopenharmony_ci kDontShare}, 230cb93a386Sopenharmony_ci }; 231cb93a386Sopenharmony_ci 232cb93a386Sopenharmony_ci for (size_t i = 0; i < SK_ARRAY_COUNT(overlappingTests); i++) { 233cb93a386Sopenharmony_ci const TestCase& test = overlappingTests[i]; 234cb93a386Sopenharmony_ci sk_sp<GrSurfaceProxy> p1 = make_proxy(dContext, test.fP1); 235cb93a386Sopenharmony_ci sk_sp<GrSurfaceProxy> p2 = make_proxy(dContext, test.fP2); 236cb93a386Sopenharmony_ci reporter->push(SkStringPrintf("case %d", SkToInt(i))); 237cb93a386Sopenharmony_ci overlap_test(reporter, dContext, std::move(p1), std::move(p2), test.fExpectation); 238cb93a386Sopenharmony_ci reporter->pop(); 239cb93a386Sopenharmony_ci } 240cb93a386Sopenharmony_ci 241cb93a386Sopenharmony_ci auto beFormat = caps->getDefaultBackendFormat(GrColorType::kRGBA_8888, GrRenderable::kYes); 242cb93a386Sopenharmony_ci int k2 = caps->getRenderTargetSampleCount(2, beFormat); 243cb93a386Sopenharmony_ci int k4 = caps->getRenderTargetSampleCount(4, beFormat); 244cb93a386Sopenharmony_ci 245cb93a386Sopenharmony_ci static const TestCase nonOverlappingTests[] = { 246cb93a386Sopenharmony_ci // Two non-overlapping intervals w/ compatible proxies should share 247cb93a386Sopenharmony_ci // both same size & approx 248cb93a386Sopenharmony_ci {{64, kRT, kRGBA, kA, 1, kNotB, kDeferred}, 249cb93a386Sopenharmony_ci {64, kRT, kRGBA, kA, 1, kNotB, kDeferred}, 250cb93a386Sopenharmony_ci kShare}, 251cb93a386Sopenharmony_ci {{64, kNotRT, kRGBA, kA, 1, kNotB, kDeferred}, 252cb93a386Sopenharmony_ci {64, kNotRT, kRGBA, kA, 1, kNotB, kDeferred}, 253cb93a386Sopenharmony_ci kConditionallyShare}, 254cb93a386Sopenharmony_ci // diffs sizes but still approx 255cb93a386Sopenharmony_ci {{64, kRT, kRGBA, kA, 1, kNotB, kDeferred}, 256cb93a386Sopenharmony_ci {50, kRT, kRGBA, kA, 1, kNotB, kDeferred}, 257cb93a386Sopenharmony_ci kShare}, 258cb93a386Sopenharmony_ci {{64, kNotRT, kRGBA, kA, 1, kNotB, kDeferred}, 259cb93a386Sopenharmony_ci {50, kNotRT, kRGBA, kA, 1, kNotB, kDeferred}, 260cb93a386Sopenharmony_ci kConditionallyShare}, 261cb93a386Sopenharmony_ci // sames sizes but exact 262cb93a386Sopenharmony_ci {{64, kRT, kRGBA, kE, 1, kNotB, kDeferred}, 263cb93a386Sopenharmony_ci {64, kRT, kRGBA, kE, 1, kNotB, kDeferred}, 264cb93a386Sopenharmony_ci kShare}, 265cb93a386Sopenharmony_ci {{64, kNotRT, kRGBA, kE, 1, kNotB, kDeferred}, 266cb93a386Sopenharmony_ci {64, kNotRT, kRGBA, kE, 1, kNotB, kDeferred}, 267cb93a386Sopenharmony_ci kConditionallyShare}, 268cb93a386Sopenharmony_ci // Two non-overlapping intervals w/ different exact sizes should not share 269cb93a386Sopenharmony_ci {{56, kRT, kRGBA, kE, 1, kNotB, kDeferred}, 270cb93a386Sopenharmony_ci {54, kRT, kRGBA, kE, 1, kNotB, kDeferred}, 271cb93a386Sopenharmony_ci kDontShare}, 272cb93a386Sopenharmony_ci // Two non-overlapping intervals w/ _very different_ approx sizes should not share 273cb93a386Sopenharmony_ci {{255, kRT, kRGBA, kA, 1, kNotB, kDeferred}, 274cb93a386Sopenharmony_ci {127, kRT, kRGBA, kA, 1, kNotB, kDeferred}, 275cb93a386Sopenharmony_ci kDontShare}, 276cb93a386Sopenharmony_ci // Two non-overlapping intervals w/ different MSAA sample counts should not share 277cb93a386Sopenharmony_ci {{64, kRT, kRGBA, kA, k2, kNotB, kDeferred}, 278cb93a386Sopenharmony_ci {64, kRT, kRGBA, kA, k4, kNotB, kDeferred}, 279cb93a386Sopenharmony_ci k2 == k4}, 280cb93a386Sopenharmony_ci // Two non-overlapping intervals w/ different configs should not share 281cb93a386Sopenharmony_ci {{64, kRT, kRGBA, kA, 1, kNotB, kDeferred}, 282cb93a386Sopenharmony_ci {64, kRT, kAlpha, kA, 1, kNotB, kDeferred}, 283cb93a386Sopenharmony_ci kDontShare}, 284cb93a386Sopenharmony_ci // Two non-overlapping intervals w/ different RT classifications should never share 285cb93a386Sopenharmony_ci {{64, kRT, kRGBA, kA, 1, kNotB, kDeferred}, 286cb93a386Sopenharmony_ci {64, kNotRT, kRGBA, kA, 1, kNotB, kDeferred}, 287cb93a386Sopenharmony_ci kDontShare}, 288cb93a386Sopenharmony_ci {{64, kNotRT, kRGBA, kA, 1, kNotB, kDeferred}, 289cb93a386Sopenharmony_ci {64, kRT, kRGBA, kA, 1, kNotB, kDeferred}, 290cb93a386Sopenharmony_ci kDontShare}, 291cb93a386Sopenharmony_ci // Two non-overlapping intervals w/ different origins should share 292cb93a386Sopenharmony_ci {{64, kRT, kRGBA, kA, 1, kNotB, kDeferred}, 293cb93a386Sopenharmony_ci {64, kRT, kRGBA, kA, 1, kNotB, kDeferred}, 294cb93a386Sopenharmony_ci kShare}, 295cb93a386Sopenharmony_ci // Wrapped backend textures should never be reused 296cb93a386Sopenharmony_ci {{64, kNotRT, kRGBA, kE, 1, kNotB, kBackend}, 297cb93a386Sopenharmony_ci {64, kNotRT, kRGBA, kE, 1, kNotB, kDeferred}, 298cb93a386Sopenharmony_ci kDontShare} 299cb93a386Sopenharmony_ci }; 300cb93a386Sopenharmony_ci 301cb93a386Sopenharmony_ci for (size_t i = 0; i < SK_ARRAY_COUNT(nonOverlappingTests); i++) { 302cb93a386Sopenharmony_ci const TestCase& test = nonOverlappingTests[i]; 303cb93a386Sopenharmony_ci sk_sp<GrSurfaceProxy> p1 = make_proxy(dContext, test.fP1); 304cb93a386Sopenharmony_ci sk_sp<GrSurfaceProxy> p2 = make_proxy(dContext, test.fP2); 305cb93a386Sopenharmony_ci 306cb93a386Sopenharmony_ci if (!p1 || !p2) { 307cb93a386Sopenharmony_ci continue; // creation can fail (e.g., for msaa4 on iOS) 308cb93a386Sopenharmony_ci } 309cb93a386Sopenharmony_ci 310cb93a386Sopenharmony_ci reporter->push(SkStringPrintf("case %d", SkToInt(i))); 311cb93a386Sopenharmony_ci non_overlap_test(reporter, dContext, std::move(p1), std::move(p2), 312cb93a386Sopenharmony_ci test.fExpectation); 313cb93a386Sopenharmony_ci reporter->pop(); 314cb93a386Sopenharmony_ci } 315cb93a386Sopenharmony_ci} 316cb93a386Sopenharmony_ci 317cb93a386Sopenharmony_cistatic void draw(GrRecordingContext* rContext) { 318cb93a386Sopenharmony_ci SkImageInfo ii = SkImageInfo::Make(1024, 1024, kRGBA_8888_SkColorType, kPremul_SkAlphaType); 319cb93a386Sopenharmony_ci 320cb93a386Sopenharmony_ci sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(rContext, SkBudgeted::kYes, 321cb93a386Sopenharmony_ci ii, 1, kTopLeft_GrSurfaceOrigin, nullptr); 322cb93a386Sopenharmony_ci 323cb93a386Sopenharmony_ci SkCanvas* c = s->getCanvas(); 324cb93a386Sopenharmony_ci 325cb93a386Sopenharmony_ci c->clear(SK_ColorBLACK); 326cb93a386Sopenharmony_ci} 327cb93a386Sopenharmony_ci 328cb93a386Sopenharmony_ci 329cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(ResourceAllocatorStressTest, reporter, ctxInfo) { 330cb93a386Sopenharmony_ci auto context = ctxInfo.directContext(); 331cb93a386Sopenharmony_ci 332cb93a386Sopenharmony_ci size_t maxBytes = context->getResourceCacheLimit(); 333cb93a386Sopenharmony_ci 334cb93a386Sopenharmony_ci context->setResourceCacheLimit(0); // We'll always be overbudget 335cb93a386Sopenharmony_ci 336cb93a386Sopenharmony_ci draw(context); 337cb93a386Sopenharmony_ci draw(context); 338cb93a386Sopenharmony_ci draw(context); 339cb93a386Sopenharmony_ci draw(context); 340cb93a386Sopenharmony_ci context->flushAndSubmit(); 341cb93a386Sopenharmony_ci 342cb93a386Sopenharmony_ci context->setResourceCacheLimit(maxBytes); 343cb93a386Sopenharmony_ci} 344cb93a386Sopenharmony_ci 345cb93a386Sopenharmony_cistruct Interval { 346cb93a386Sopenharmony_ci ProxyParams fParams; 347cb93a386Sopenharmony_ci int fStart; 348cb93a386Sopenharmony_ci int fEnd; 349cb93a386Sopenharmony_ci sk_sp<GrSurfaceProxy> fProxy = nullptr; 350cb93a386Sopenharmony_ci}; 351cb93a386Sopenharmony_ci 352cb93a386Sopenharmony_cistruct TestCase { 353cb93a386Sopenharmony_ci const char * fName; 354cb93a386Sopenharmony_ci bool fShouldFit; 355cb93a386Sopenharmony_ci size_t fBudget; 356cb93a386Sopenharmony_ci SkTArray<ProxyParams> fPurgeableResourcesInCache = {}; 357cb93a386Sopenharmony_ci SkTArray<ProxyParams> fUnpurgeableResourcesInCache = {}; 358cb93a386Sopenharmony_ci SkTArray<Interval> fIntervals; 359cb93a386Sopenharmony_ci}; 360cb93a386Sopenharmony_ci 361cb93a386Sopenharmony_cistatic void memory_budget_test(skiatest::Reporter* reporter, 362cb93a386Sopenharmony_ci GrDirectContext* dContext, 363cb93a386Sopenharmony_ci const TestCase& test) { 364cb93a386Sopenharmony_ci // Reset cache. 365cb93a386Sopenharmony_ci auto cache = dContext->priv().getResourceCache(); 366cb93a386Sopenharmony_ci cache->releaseAll(); 367cb93a386Sopenharmony_ci cache->setLimit(test.fBudget); 368cb93a386Sopenharmony_ci 369cb93a386Sopenharmony_ci // Add purgeable entries. 370cb93a386Sopenharmony_ci size_t expectedPurgeableBytes = 0; 371cb93a386Sopenharmony_ci SkTArray<sk_sp<GrSurface>> purgeableSurfaces; 372cb93a386Sopenharmony_ci for (auto& params : test.fPurgeableResourcesInCache) { 373cb93a386Sopenharmony_ci SkASSERT(params.fKind == kInstantiated); 374cb93a386Sopenharmony_ci sk_sp<GrSurfaceProxy> proxy = make_proxy(dContext, params); 375cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, proxy->peekSurface()); 376cb93a386Sopenharmony_ci expectedPurgeableBytes += proxy->gpuMemorySize(); 377cb93a386Sopenharmony_ci purgeableSurfaces.push_back(sk_ref_sp(proxy->peekSurface())); 378cb93a386Sopenharmony_ci } 379cb93a386Sopenharmony_ci purgeableSurfaces.reset(); 380cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, expectedPurgeableBytes == cache->getPurgeableBytes(), 381cb93a386Sopenharmony_ci "%zu", cache->getPurgeableBytes()); 382cb93a386Sopenharmony_ci 383cb93a386Sopenharmony_ci // Add unpurgeable entries. 384cb93a386Sopenharmony_ci size_t expectedUnpurgeableBytes = 0; 385cb93a386Sopenharmony_ci SkTArray<sk_sp<GrSurface>> unpurgeableSurfaces; 386cb93a386Sopenharmony_ci for (auto& params : test.fUnpurgeableResourcesInCache) { 387cb93a386Sopenharmony_ci SkASSERT(params.fKind == kInstantiated); 388cb93a386Sopenharmony_ci sk_sp<GrSurfaceProxy> proxy = make_proxy(dContext, params); 389cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, proxy->peekSurface()); 390cb93a386Sopenharmony_ci expectedUnpurgeableBytes += proxy->gpuMemorySize(); 391cb93a386Sopenharmony_ci unpurgeableSurfaces.push_back(sk_ref_sp(proxy->peekSurface())); 392cb93a386Sopenharmony_ci } 393cb93a386Sopenharmony_ci 394cb93a386Sopenharmony_ci auto unpurgeableBytes = cache->getBudgetedResourceBytes() - cache->getPurgeableBytes(); 395cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, expectedUnpurgeableBytes == unpurgeableBytes, 396cb93a386Sopenharmony_ci "%zu", unpurgeableBytes); 397cb93a386Sopenharmony_ci 398cb93a386Sopenharmony_ci // Add intervals and test. 399cb93a386Sopenharmony_ci GrResourceAllocator alloc(dContext); 400cb93a386Sopenharmony_ci for (auto& interval : test.fIntervals) { 401cb93a386Sopenharmony_ci for (int i = interval.fStart; i <= interval.fEnd; i++) { 402cb93a386Sopenharmony_ci alloc.incOps(); 403cb93a386Sopenharmony_ci } 404cb93a386Sopenharmony_ci alloc.addInterval(interval.fProxy.get(), interval.fStart, interval.fEnd, 405cb93a386Sopenharmony_ci GrResourceAllocator::ActualUse::kYes); 406cb93a386Sopenharmony_ci } 407cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, alloc.planAssignment()); 408cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, alloc.makeBudgetHeadroom() == test.fShouldFit); 409cb93a386Sopenharmony_ci} 410cb93a386Sopenharmony_ci 411cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(ResourceAllocatorMemoryBudgetTest, reporter, ctxInfo) { 412cb93a386Sopenharmony_ci auto dContext = ctxInfo.directContext(); 413cb93a386Sopenharmony_ci 414cb93a386Sopenharmony_ci constexpr bool kUnder = true; 415cb93a386Sopenharmony_ci constexpr bool kOver = false; 416cb93a386Sopenharmony_ci constexpr size_t kRGBA64Bytes = 4 * 64 * 64; 417cb93a386Sopenharmony_ci const ProxyParams kProxy64 = {64, kRT, kRGBA, kE, 1, kB, kDeferred}; 418cb93a386Sopenharmony_ci const ProxyParams kProxy64NotBudgeted = {64, kRT, kRGBA, kE, 1, kNotB, kDeferred}; 419cb93a386Sopenharmony_ci const ProxyParams kProxy64Lazy = {64, kRT, kRGBA, kE, 1, kB, kLazy}; 420cb93a386Sopenharmony_ci const ProxyParams kProxy64FullyLazy = {64, kRT, kRGBA, kE, 1, kB, kFullyLazy}; 421cb93a386Sopenharmony_ci const ProxyParams kProxy32Instantiated = {32, kRT, kRGBA, kE, 1, kB, kInstantiated}; 422cb93a386Sopenharmony_ci const ProxyParams kProxy64Instantiated = {64, kRT, kRGBA, kE, 1, kB, kInstantiated}; 423cb93a386Sopenharmony_ci 424cb93a386Sopenharmony_ci TestCase tests[] = { 425cb93a386Sopenharmony_ci {"empty DAG", kUnder, 0, {}, {}, {}}, 426cb93a386Sopenharmony_ci {"unbudgeted", kUnder, 0, {}, {}, {{kProxy64NotBudgeted, 0, 2}}}, 427cb93a386Sopenharmony_ci {"basic", kUnder, kRGBA64Bytes, {}, {}, {{kProxy64, 0, 2}}}, 428cb93a386Sopenharmony_ci {"basic, over", kOver, kRGBA64Bytes - 1, {}, {}, {{kProxy64, 0, 2}}}, 429cb93a386Sopenharmony_ci {"shared", kUnder, kRGBA64Bytes, {}, {}, 430cb93a386Sopenharmony_ci { 431cb93a386Sopenharmony_ci {kProxy64, 0, 2}, 432cb93a386Sopenharmony_ci {kProxy64, 3, 5}, 433cb93a386Sopenharmony_ci }}, 434cb93a386Sopenharmony_ci {"retrieved from cache", kUnder, kRGBA64Bytes, 435cb93a386Sopenharmony_ci /* purgeable */{kProxy64Instantiated}, 436cb93a386Sopenharmony_ci /* unpurgeable */{}, 437cb93a386Sopenharmony_ci { 438cb93a386Sopenharmony_ci {kProxy64, 0, 2} 439cb93a386Sopenharmony_ci }}, 440cb93a386Sopenharmony_ci {"purge 4", kUnder, kRGBA64Bytes, 441cb93a386Sopenharmony_ci /* purgeable */{ 442cb93a386Sopenharmony_ci kProxy32Instantiated, 443cb93a386Sopenharmony_ci kProxy32Instantiated, 444cb93a386Sopenharmony_ci kProxy32Instantiated, 445cb93a386Sopenharmony_ci kProxy32Instantiated 446cb93a386Sopenharmony_ci }, 447cb93a386Sopenharmony_ci /* unpurgeable */{}, 448cb93a386Sopenharmony_ci { 449cb93a386Sopenharmony_ci {kProxy64, 0, 2} 450cb93a386Sopenharmony_ci }}, 451cb93a386Sopenharmony_ci {"dont purge what we've reserved", kOver, kRGBA64Bytes, 452cb93a386Sopenharmony_ci /* purgeable */{kProxy64Instantiated}, 453cb93a386Sopenharmony_ci /* unpurgeable */{}, 454cb93a386Sopenharmony_ci { 455cb93a386Sopenharmony_ci {kProxy64, 0, 2}, 456cb93a386Sopenharmony_ci {kProxy64, 1, 3} 457cb93a386Sopenharmony_ci }}, 458cb93a386Sopenharmony_ci {"unpurgeable", kOver, kRGBA64Bytes, 459cb93a386Sopenharmony_ci /* purgeable */{}, 460cb93a386Sopenharmony_ci /* unpurgeable */{kProxy64Instantiated}, 461cb93a386Sopenharmony_ci { 462cb93a386Sopenharmony_ci {kProxy64, 0, 2} 463cb93a386Sopenharmony_ci }}, 464cb93a386Sopenharmony_ci {"lazy", kUnder, kRGBA64Bytes, 465cb93a386Sopenharmony_ci /* purgeable */{}, 466cb93a386Sopenharmony_ci /* unpurgeable */{}, 467cb93a386Sopenharmony_ci { 468cb93a386Sopenharmony_ci {kProxy64Lazy, 0, 2} 469cb93a386Sopenharmony_ci }}, 470cb93a386Sopenharmony_ci {"lazy, over", kOver, kRGBA64Bytes - 1, 471cb93a386Sopenharmony_ci /* purgeable */{}, 472cb93a386Sopenharmony_ci /* unpurgeable */{}, 473cb93a386Sopenharmony_ci { 474cb93a386Sopenharmony_ci {kProxy64Lazy, 0, 2} 475cb93a386Sopenharmony_ci }}, 476cb93a386Sopenharmony_ci {"fully-lazy", kUnder, kRGBA64Bytes, 477cb93a386Sopenharmony_ci /* purgeable */{}, 478cb93a386Sopenharmony_ci /* unpurgeable */{}, 479cb93a386Sopenharmony_ci { 480cb93a386Sopenharmony_ci {kProxy64FullyLazy, 0, 2} 481cb93a386Sopenharmony_ci }}, 482cb93a386Sopenharmony_ci {"fully-lazy, over", kOver, kRGBA64Bytes - 1, 483cb93a386Sopenharmony_ci /* purgeable */{}, 484cb93a386Sopenharmony_ci /* unpurgeable */{}, 485cb93a386Sopenharmony_ci { 486cb93a386Sopenharmony_ci {kProxy64FullyLazy, 0, 2} 487cb93a386Sopenharmony_ci }}, 488cb93a386Sopenharmony_ci }; 489cb93a386Sopenharmony_ci SkString match(""); 490cb93a386Sopenharmony_ci for (size_t i = 0; i < SK_ARRAY_COUNT(tests); i++) { 491cb93a386Sopenharmony_ci TestCase& test = tests[i]; 492cb93a386Sopenharmony_ci if (match.isEmpty() || match == SkString(test.fName)) { 493cb93a386Sopenharmony_ci // Create proxies 494cb93a386Sopenharmony_ci for (Interval& interval : test.fIntervals) { 495cb93a386Sopenharmony_ci interval.fProxy = make_proxy(dContext, interval.fParams); 496cb93a386Sopenharmony_ci } 497cb93a386Sopenharmony_ci reporter->push(SkString(test.fName)); 498cb93a386Sopenharmony_ci memory_budget_test(reporter, dContext, test); 499cb93a386Sopenharmony_ci reporter->pop(); 500cb93a386Sopenharmony_ci } 501cb93a386Sopenharmony_ci } 502cb93a386Sopenharmony_ci} 503cb93a386Sopenharmony_ci 504