1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2013 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkAlphaType.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBitmap.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorType.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkData.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImageInfo.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/GpuTypes.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrBackendSurface.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrDirectContext.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrRecordingContext.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrTypes.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/SkSurfaceGanesh.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkDebug.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTDArray.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTo.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/gpu/ganesh/GrTypesPriv.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkRandom.h"
33*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkMessageBus.h"
34*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/GpuTypesPriv.h"
35*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ResourceKey.h"
36*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/SkBackingFit.h"
37*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrCaps.h"
38*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrDirectContextPriv.h"
39*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrGpu.h"
40*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrGpuResource.h"
41*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrGpuResourceCacheAccess.h"
42*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrGpuResourcePriv.h"
43*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrProxyProvider.h"
44*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrRecordingContextPriv.h"
45*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrRenderTarget.h"
46*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrResourceCache.h"
47*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrResourceProvider.h"
48*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrTexture.h"
49*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrTextureProxy.h"
50*c8dee2aaSAndroid Build Coastguard Worker #include "tests/CtsEnforcement.h"
51*c8dee2aaSAndroid Build Coastguard Worker #include "tests/Test.h"
52*c8dee2aaSAndroid Build Coastguard Worker #include "tools/gpu/ContextType.h"
53*c8dee2aaSAndroid Build Coastguard Worker #include "tools/gpu/ManagedBackendTexture.h"
54*c8dee2aaSAndroid Build Coastguard Worker
55*c8dee2aaSAndroid Build Coastguard Worker #include <chrono>
56*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef>
57*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
58*c8dee2aaSAndroid Build Coastguard Worker #include <initializer_list>
59*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
60*c8dee2aaSAndroid Build Coastguard Worker #include <string_view>
61*c8dee2aaSAndroid Build Coastguard Worker #include <thread>
62*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
63*c8dee2aaSAndroid Build Coastguard Worker #include <vector>
64*c8dee2aaSAndroid Build Coastguard Worker
65*c8dee2aaSAndroid Build Coastguard Worker class GrAttachment;
66*c8dee2aaSAndroid Build Coastguard Worker struct GrContextOptions;
67*c8dee2aaSAndroid Build Coastguard Worker
68*c8dee2aaSAndroid Build Coastguard Worker static const int gWidth = 640;
69*c8dee2aaSAndroid Build Coastguard Worker static const int gHeight = 480;
70*c8dee2aaSAndroid Build Coastguard Worker
71*c8dee2aaSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ResourceCacheCache,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)72*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ResourceCacheCache,
73*c8dee2aaSAndroid Build Coastguard Worker reporter,
74*c8dee2aaSAndroid Build Coastguard Worker ctxInfo,
75*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_T) {
76*c8dee2aaSAndroid Build Coastguard Worker auto context = ctxInfo.directContext();
77*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo info = SkImageInfo::MakeN32Premul(gWidth, gHeight);
78*c8dee2aaSAndroid Build Coastguard Worker auto surface(SkSurfaces::RenderTarget(context, skgpu::Budgeted::kNo, info));
79*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* canvas = surface->getCanvas();
80*c8dee2aaSAndroid Build Coastguard Worker
81*c8dee2aaSAndroid Build Coastguard Worker const SkIRect size = SkIRect::MakeWH(gWidth, gHeight);
82*c8dee2aaSAndroid Build Coastguard Worker
83*c8dee2aaSAndroid Build Coastguard Worker SkBitmap src;
84*c8dee2aaSAndroid Build Coastguard Worker src.allocN32Pixels(size.width(), size.height());
85*c8dee2aaSAndroid Build Coastguard Worker src.eraseColor(SK_ColorBLACK);
86*c8dee2aaSAndroid Build Coastguard Worker size_t srcSize = src.computeByteSize();
87*c8dee2aaSAndroid Build Coastguard Worker
88*c8dee2aaSAndroid Build Coastguard Worker size_t initialCacheSize;
89*c8dee2aaSAndroid Build Coastguard Worker context->getResourceCacheUsage(nullptr, &initialCacheSize);
90*c8dee2aaSAndroid Build Coastguard Worker
91*c8dee2aaSAndroid Build Coastguard Worker size_t oldMaxBytes = context->getResourceCacheLimit();
92*c8dee2aaSAndroid Build Coastguard Worker
93*c8dee2aaSAndroid Build Coastguard Worker // Set the cache limits so we can fit 10 "src" images and the
94*c8dee2aaSAndroid Build Coastguard Worker // max number of textures doesn't matter
95*c8dee2aaSAndroid Build Coastguard Worker size_t maxCacheSize = initialCacheSize + 10*srcSize;
96*c8dee2aaSAndroid Build Coastguard Worker context->setResourceCacheLimit(maxCacheSize);
97*c8dee2aaSAndroid Build Coastguard Worker
98*c8dee2aaSAndroid Build Coastguard Worker SkBitmap readback;
99*c8dee2aaSAndroid Build Coastguard Worker readback.allocN32Pixels(size.width(), size.height());
100*c8dee2aaSAndroid Build Coastguard Worker
101*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 100; ++i) {
102*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(src.asImage(), 0, 0);
103*c8dee2aaSAndroid Build Coastguard Worker surface->readPixels(readback, 0, 0);
104*c8dee2aaSAndroid Build Coastguard Worker
105*c8dee2aaSAndroid Build Coastguard Worker // "modify" the src texture
106*c8dee2aaSAndroid Build Coastguard Worker src.notifyPixelsChanged();
107*c8dee2aaSAndroid Build Coastguard Worker
108*c8dee2aaSAndroid Build Coastguard Worker size_t curCacheSize;
109*c8dee2aaSAndroid Build Coastguard Worker context->getResourceCacheUsage(nullptr, &curCacheSize);
110*c8dee2aaSAndroid Build Coastguard Worker
111*c8dee2aaSAndroid Build Coastguard Worker // we should never go over the size limit
112*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, curCacheSize <= maxCacheSize);
113*c8dee2aaSAndroid Build Coastguard Worker }
114*c8dee2aaSAndroid Build Coastguard Worker
115*c8dee2aaSAndroid Build Coastguard Worker context->setResourceCacheLimit(oldMaxBytes);
116*c8dee2aaSAndroid Build Coastguard Worker }
117*c8dee2aaSAndroid Build Coastguard Worker
is_rendering_and_not_angle_es3(skgpu::ContextType type)118*c8dee2aaSAndroid Build Coastguard Worker static bool is_rendering_and_not_angle_es3(skgpu::ContextType type) {
119*c8dee2aaSAndroid Build Coastguard Worker if (type == skgpu::ContextType::kANGLE_D3D11_ES3 ||
120*c8dee2aaSAndroid Build Coastguard Worker type == skgpu::ContextType::kANGLE_GL_ES3 ||
121*c8dee2aaSAndroid Build Coastguard Worker type == skgpu::ContextType::kANGLE_Metal_ES3) {
122*c8dee2aaSAndroid Build Coastguard Worker return false;
123*c8dee2aaSAndroid Build Coastguard Worker }
124*c8dee2aaSAndroid Build Coastguard Worker return skgpu::IsRenderingContext(type);
125*c8dee2aaSAndroid Build Coastguard Worker }
126*c8dee2aaSAndroid Build Coastguard Worker
get_SB(GrRenderTarget * rt)127*c8dee2aaSAndroid Build Coastguard Worker static GrAttachment* get_SB(GrRenderTarget* rt) { return rt->getStencilAttachment(); }
128*c8dee2aaSAndroid Build Coastguard Worker
create_RT_with_SB(GrResourceProvider * provider,int size,int sampleCount,skgpu::Budgeted budgeted)129*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<GrRenderTarget> create_RT_with_SB(GrResourceProvider* provider,
130*c8dee2aaSAndroid Build Coastguard Worker int size,
131*c8dee2aaSAndroid Build Coastguard Worker int sampleCount,
132*c8dee2aaSAndroid Build Coastguard Worker skgpu::Budgeted budgeted) {
133*c8dee2aaSAndroid Build Coastguard Worker auto format =
134*c8dee2aaSAndroid Build Coastguard Worker provider->caps()->getDefaultBackendFormat(GrColorType::kRGBA_8888, GrRenderable::kYes);
135*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> tex(provider->createTexture({size, size},
136*c8dee2aaSAndroid Build Coastguard Worker format,
137*c8dee2aaSAndroid Build Coastguard Worker GrTextureType::k2D,
138*c8dee2aaSAndroid Build Coastguard Worker GrRenderable::kYes,
139*c8dee2aaSAndroid Build Coastguard Worker sampleCount,
140*c8dee2aaSAndroid Build Coastguard Worker skgpu::Mipmapped::kNo,
141*c8dee2aaSAndroid Build Coastguard Worker budgeted,
142*c8dee2aaSAndroid Build Coastguard Worker GrProtected::kNo,
143*c8dee2aaSAndroid Build Coastguard Worker /*label=*/{}));
144*c8dee2aaSAndroid Build Coastguard Worker if (!tex || !tex->asRenderTarget()) {
145*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
146*c8dee2aaSAndroid Build Coastguard Worker }
147*c8dee2aaSAndroid Build Coastguard Worker
148*c8dee2aaSAndroid Build Coastguard Worker if (!provider->attachStencilAttachment(tex->asRenderTarget(), sampleCount > 1)) {
149*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
150*c8dee2aaSAndroid Build Coastguard Worker }
151*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(get_SB(tex->asRenderTarget()));
152*c8dee2aaSAndroid Build Coastguard Worker
153*c8dee2aaSAndroid Build Coastguard Worker return sk_ref_sp(tex->asRenderTarget());
154*c8dee2aaSAndroid Build Coastguard Worker }
155*c8dee2aaSAndroid Build Coastguard Worker
156*c8dee2aaSAndroid Build Coastguard Worker // This currently fails on ES3 ANGLE contexts
157*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_CONTEXTS(ResourceCacheStencilBuffers,
158*c8dee2aaSAndroid Build Coastguard Worker &is_rendering_and_not_angle_es3,
159*c8dee2aaSAndroid Build Coastguard Worker reporter,
160*c8dee2aaSAndroid Build Coastguard Worker ctxInfo,
161*c8dee2aaSAndroid Build Coastguard Worker nullptr,
162*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_T) {
163*c8dee2aaSAndroid Build Coastguard Worker auto context = ctxInfo.directContext();
164*c8dee2aaSAndroid Build Coastguard Worker const GrCaps* caps = context->priv().caps();
165*c8dee2aaSAndroid Build Coastguard Worker
166*c8dee2aaSAndroid Build Coastguard Worker if (caps->avoidStencilBuffers()) {
167*c8dee2aaSAndroid Build Coastguard Worker return;
168*c8dee2aaSAndroid Build Coastguard Worker }
169*c8dee2aaSAndroid Build Coastguard Worker
170*c8dee2aaSAndroid Build Coastguard Worker GrResourceProvider* resourceProvider = context->priv().resourceProvider();
171*c8dee2aaSAndroid Build Coastguard Worker
172*c8dee2aaSAndroid Build Coastguard Worker GrColorType grColorType = GrColorType::kRGBA_8888;
173*c8dee2aaSAndroid Build Coastguard Worker GrBackendFormat format = caps->getDefaultBackendFormat(grColorType, GrRenderable::kYes);
174*c8dee2aaSAndroid Build Coastguard Worker
175*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrRenderTarget> smallRT0 =
176*c8dee2aaSAndroid Build Coastguard Worker create_RT_with_SB(resourceProvider, 4, 1, skgpu::Budgeted::kYes);
177*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, smallRT0);
178*c8dee2aaSAndroid Build Coastguard Worker
179*c8dee2aaSAndroid Build Coastguard Worker {
180*c8dee2aaSAndroid Build Coastguard Worker // Two budgeted RTs with the same desc should share a stencil buffer.
181*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrRenderTarget> smallRT1 =
182*c8dee2aaSAndroid Build Coastguard Worker create_RT_with_SB(resourceProvider, 4, 1, skgpu::Budgeted::kYes);
183*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, smallRT1);
184*c8dee2aaSAndroid Build Coastguard Worker
185*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, get_SB(smallRT0.get()) == get_SB(smallRT1.get()));
186*c8dee2aaSAndroid Build Coastguard Worker }
187*c8dee2aaSAndroid Build Coastguard Worker
188*c8dee2aaSAndroid Build Coastguard Worker {
189*c8dee2aaSAndroid Build Coastguard Worker // An unbudgeted RT with the same desc should also share.
190*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrRenderTarget> smallRT2 =
191*c8dee2aaSAndroid Build Coastguard Worker create_RT_with_SB(resourceProvider, 4, 1, skgpu::Budgeted::kNo);
192*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, smallRT2);
193*c8dee2aaSAndroid Build Coastguard Worker
194*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, get_SB(smallRT0.get()) == get_SB(smallRT2.get()));
195*c8dee2aaSAndroid Build Coastguard Worker }
196*c8dee2aaSAndroid Build Coastguard Worker
197*c8dee2aaSAndroid Build Coastguard Worker {
198*c8dee2aaSAndroid Build Coastguard Worker // An RT with a much larger size should not share.
199*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrRenderTarget> bigRT =
200*c8dee2aaSAndroid Build Coastguard Worker create_RT_with_SB(resourceProvider, 400, 1, skgpu::Budgeted::kNo);
201*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, bigRT);
202*c8dee2aaSAndroid Build Coastguard Worker
203*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, get_SB(smallRT0.get()) != get_SB(bigRT.get()));
204*c8dee2aaSAndroid Build Coastguard Worker }
205*c8dee2aaSAndroid Build Coastguard Worker
206*c8dee2aaSAndroid Build Coastguard Worker int smallSampleCount =
207*c8dee2aaSAndroid Build Coastguard Worker context->priv().caps()->getRenderTargetSampleCount(2, format);
208*c8dee2aaSAndroid Build Coastguard Worker if (smallSampleCount > 1) {
209*c8dee2aaSAndroid Build Coastguard Worker // An RT with a different sample count should not share.
210*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrRenderTarget> smallMSAART0 =
211*c8dee2aaSAndroid Build Coastguard Worker create_RT_with_SB(resourceProvider, 4, smallSampleCount, skgpu::Budgeted::kNo);
212*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, smallMSAART0);
213*c8dee2aaSAndroid Build Coastguard Worker
214*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, get_SB(smallRT0.get()) != get_SB(smallMSAART0.get()));
215*c8dee2aaSAndroid Build Coastguard Worker
216*c8dee2aaSAndroid Build Coastguard Worker {
217*c8dee2aaSAndroid Build Coastguard Worker // A second MSAA RT should share with the first MSAA RT.
218*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrRenderTarget> smallMSAART1 =
219*c8dee2aaSAndroid Build Coastguard Worker create_RT_with_SB(resourceProvider, 4, smallSampleCount, skgpu::Budgeted::kNo);
220*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, smallMSAART1);
221*c8dee2aaSAndroid Build Coastguard Worker
222*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, get_SB(smallMSAART0.get()) == get_SB(smallMSAART1.get()));
223*c8dee2aaSAndroid Build Coastguard Worker }
224*c8dee2aaSAndroid Build Coastguard Worker
225*c8dee2aaSAndroid Build Coastguard Worker // But one with a larger sample count should not. (Also check that the two requests didn't
226*c8dee2aaSAndroid Build Coastguard Worker // rounded up to the same actual sample count or else they could share.).
227*c8dee2aaSAndroid Build Coastguard Worker int bigSampleCount = context->priv().caps()->getRenderTargetSampleCount(5, format);
228*c8dee2aaSAndroid Build Coastguard Worker if (bigSampleCount > 0 && bigSampleCount != smallSampleCount) {
229*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrRenderTarget> smallMSAART2 =
230*c8dee2aaSAndroid Build Coastguard Worker create_RT_with_SB(resourceProvider, 4, bigSampleCount, skgpu::Budgeted::kNo);
231*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, smallMSAART2);
232*c8dee2aaSAndroid Build Coastguard Worker
233*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, get_SB(smallMSAART0.get()) != get_SB(smallMSAART2.get()));
234*c8dee2aaSAndroid Build Coastguard Worker }
235*c8dee2aaSAndroid Build Coastguard Worker }
236*c8dee2aaSAndroid Build Coastguard Worker }
237*c8dee2aaSAndroid Build Coastguard Worker
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ResourceCacheWrappedResources,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)238*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ResourceCacheWrappedResources,
239*c8dee2aaSAndroid Build Coastguard Worker reporter,
240*c8dee2aaSAndroid Build Coastguard Worker ctxInfo,
241*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_T) {
242*c8dee2aaSAndroid Build Coastguard Worker auto context = ctxInfo.directContext();
243*c8dee2aaSAndroid Build Coastguard Worker GrResourceProvider* resourceProvider = context->priv().resourceProvider();
244*c8dee2aaSAndroid Build Coastguard Worker GrGpu* gpu = context->priv().getGpu();
245*c8dee2aaSAndroid Build Coastguard Worker // this test is only valid for GL
246*c8dee2aaSAndroid Build Coastguard Worker if (!gpu || !gpu->glContextForTesting()) {
247*c8dee2aaSAndroid Build Coastguard Worker return;
248*c8dee2aaSAndroid Build Coastguard Worker }
249*c8dee2aaSAndroid Build Coastguard Worker
250*c8dee2aaSAndroid Build Coastguard Worker static const int kW = 100;
251*c8dee2aaSAndroid Build Coastguard Worker static const int kH = 100;
252*c8dee2aaSAndroid Build Coastguard Worker
253*c8dee2aaSAndroid Build Coastguard Worker auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(
254*c8dee2aaSAndroid Build Coastguard Worker context, kW, kH, kRGBA_8888_SkColorType, skgpu::Mipmapped::kNo, GrRenderable::kNo);
255*c8dee2aaSAndroid Build Coastguard Worker GrBackendTexture unmbet = context->createBackendTexture(
256*c8dee2aaSAndroid Build Coastguard Worker kW, kH, kRGBA_8888_SkColorType, skgpu::Mipmapped::kNo, GrRenderable::kNo);
257*c8dee2aaSAndroid Build Coastguard Worker if (!mbet || !unmbet.isValid()) {
258*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Could not create backend texture.");
259*c8dee2aaSAndroid Build Coastguard Worker return;
260*c8dee2aaSAndroid Build Coastguard Worker }
261*c8dee2aaSAndroid Build Coastguard Worker
262*c8dee2aaSAndroid Build Coastguard Worker context->resetContext();
263*c8dee2aaSAndroid Build Coastguard Worker
264*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> borrowed(resourceProvider->wrapBackendTexture(
265*c8dee2aaSAndroid Build Coastguard Worker mbet->texture(), kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, kRead_GrIOType));
266*c8dee2aaSAndroid Build Coastguard Worker
267*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> adopted(resourceProvider->wrapBackendTexture(
268*c8dee2aaSAndroid Build Coastguard Worker unmbet, kAdopt_GrWrapOwnership, GrWrapCacheable::kNo, kRead_GrIOType));
269*c8dee2aaSAndroid Build Coastguard Worker
270*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, borrowed != nullptr && adopted != nullptr);
271*c8dee2aaSAndroid Build Coastguard Worker if (!borrowed || !adopted) {
272*c8dee2aaSAndroid Build Coastguard Worker return;
273*c8dee2aaSAndroid Build Coastguard Worker }
274*c8dee2aaSAndroid Build Coastguard Worker
275*c8dee2aaSAndroid Build Coastguard Worker borrowed.reset();
276*c8dee2aaSAndroid Build Coastguard Worker adopted.reset();
277*c8dee2aaSAndroid Build Coastguard Worker
278*c8dee2aaSAndroid Build Coastguard Worker context->flushAndSubmit(GrSyncCpu::kYes);
279*c8dee2aaSAndroid Build Coastguard Worker
280*c8dee2aaSAndroid Build Coastguard Worker bool borrowedIsAlive = gpu->isTestingOnlyBackendTexture(mbet->texture());
281*c8dee2aaSAndroid Build Coastguard Worker bool adoptedIsAlive = gpu->isTestingOnlyBackendTexture(unmbet);
282*c8dee2aaSAndroid Build Coastguard Worker
283*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, borrowedIsAlive);
284*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !adoptedIsAlive);
285*c8dee2aaSAndroid Build Coastguard Worker
286*c8dee2aaSAndroid Build Coastguard Worker if (adoptedIsAlive) {
287*c8dee2aaSAndroid Build Coastguard Worker context->deleteBackendTexture(unmbet);
288*c8dee2aaSAndroid Build Coastguard Worker }
289*c8dee2aaSAndroid Build Coastguard Worker
290*c8dee2aaSAndroid Build Coastguard Worker context->resetContext();
291*c8dee2aaSAndroid Build Coastguard Worker }
292*c8dee2aaSAndroid Build Coastguard Worker
293*c8dee2aaSAndroid Build Coastguard Worker class TestResource : public GrGpuResource {
294*c8dee2aaSAndroid Build Coastguard Worker enum ScratchConstructor { kScratchConstructor };
295*c8dee2aaSAndroid Build Coastguard Worker public:
296*c8dee2aaSAndroid Build Coastguard Worker static const size_t kDefaultSize = 100;
297*c8dee2aaSAndroid Build Coastguard Worker
298*c8dee2aaSAndroid Build Coastguard Worker /** Property that distinctly categorizes the resource.
299*c8dee2aaSAndroid Build Coastguard Worker * For example, textures have width, height, ... */
300*c8dee2aaSAndroid Build Coastguard Worker enum SimulatedProperty { kA_SimulatedProperty, kB_SimulatedProperty };
301*c8dee2aaSAndroid Build Coastguard Worker
TestResource(GrGpu * gpu,std::string_view label,skgpu::Budgeted budgeted=skgpu::Budgeted::kYes,size_t size=kDefaultSize)302*c8dee2aaSAndroid Build Coastguard Worker TestResource(GrGpu* gpu,
303*c8dee2aaSAndroid Build Coastguard Worker std::string_view label,
304*c8dee2aaSAndroid Build Coastguard Worker skgpu::Budgeted budgeted = skgpu::Budgeted::kYes,
305*c8dee2aaSAndroid Build Coastguard Worker size_t size = kDefaultSize)
306*c8dee2aaSAndroid Build Coastguard Worker : INHERITED(gpu, label)
307*c8dee2aaSAndroid Build Coastguard Worker , fToDelete(nullptr)
308*c8dee2aaSAndroid Build Coastguard Worker , fSize(size)
309*c8dee2aaSAndroid Build Coastguard Worker , fProperty(kA_SimulatedProperty)
310*c8dee2aaSAndroid Build Coastguard Worker , fIsScratch(false) {
311*c8dee2aaSAndroid Build Coastguard Worker ++fNumAlive;
312*c8dee2aaSAndroid Build Coastguard Worker this->registerWithCache(budgeted);
313*c8dee2aaSAndroid Build Coastguard Worker }
314*c8dee2aaSAndroid Build Coastguard Worker
CreateScratch(GrGpu * gpu,skgpu::Budgeted budgeted,SimulatedProperty property,size_t size=kDefaultSize)315*c8dee2aaSAndroid Build Coastguard Worker static TestResource* CreateScratch(GrGpu* gpu,
316*c8dee2aaSAndroid Build Coastguard Worker skgpu::Budgeted budgeted,
317*c8dee2aaSAndroid Build Coastguard Worker SimulatedProperty property,
318*c8dee2aaSAndroid Build Coastguard Worker size_t size = kDefaultSize) {
319*c8dee2aaSAndroid Build Coastguard Worker return new TestResource(gpu, budgeted, property, kScratchConstructor, /*label=*/{}, size);
320*c8dee2aaSAndroid Build Coastguard Worker }
CreateWrapped(GrGpu * gpu,GrWrapCacheable cacheable,size_t size=kDefaultSize)321*c8dee2aaSAndroid Build Coastguard Worker static TestResource* CreateWrapped(GrGpu* gpu,
322*c8dee2aaSAndroid Build Coastguard Worker GrWrapCacheable cacheable,
323*c8dee2aaSAndroid Build Coastguard Worker size_t size = kDefaultSize) {
324*c8dee2aaSAndroid Build Coastguard Worker return new TestResource(gpu, cacheable, size, /*label=*/{});
325*c8dee2aaSAndroid Build Coastguard Worker }
326*c8dee2aaSAndroid Build Coastguard Worker
~TestResource()327*c8dee2aaSAndroid Build Coastguard Worker ~TestResource() override {
328*c8dee2aaSAndroid Build Coastguard Worker --fNumAlive;
329*c8dee2aaSAndroid Build Coastguard Worker }
330*c8dee2aaSAndroid Build Coastguard Worker
NumAlive()331*c8dee2aaSAndroid Build Coastguard Worker static int NumAlive() { return fNumAlive; }
332*c8dee2aaSAndroid Build Coastguard Worker
setUnrefWhenDestroyed(sk_sp<TestResource> resource)333*c8dee2aaSAndroid Build Coastguard Worker void setUnrefWhenDestroyed(sk_sp<TestResource> resource) {
334*c8dee2aaSAndroid Build Coastguard Worker fToDelete = std::move(resource);
335*c8dee2aaSAndroid Build Coastguard Worker }
336*c8dee2aaSAndroid Build Coastguard Worker
ComputeScratchKey(SimulatedProperty property,skgpu::ScratchKey * key)337*c8dee2aaSAndroid Build Coastguard Worker static void ComputeScratchKey(SimulatedProperty property, skgpu::ScratchKey* key) {
338*c8dee2aaSAndroid Build Coastguard Worker static skgpu::ScratchKey::ResourceType t = skgpu::ScratchKey::GenerateResourceType();
339*c8dee2aaSAndroid Build Coastguard Worker skgpu::ScratchKey::Builder builder(key, t, kScratchKeyFieldCnt);
340*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < kScratchKeyFieldCnt; ++i) {
341*c8dee2aaSAndroid Build Coastguard Worker builder[i] = static_cast<uint32_t>(i + property);
342*c8dee2aaSAndroid Build Coastguard Worker }
343*c8dee2aaSAndroid Build Coastguard Worker }
344*c8dee2aaSAndroid Build Coastguard Worker
ExpectedScratchKeySize()345*c8dee2aaSAndroid Build Coastguard Worker static size_t ExpectedScratchKeySize() {
346*c8dee2aaSAndroid Build Coastguard Worker return sizeof(uint32_t) * (kScratchKeyFieldCnt + skgpu::ScratchKey::kMetaDataCnt);
347*c8dee2aaSAndroid Build Coastguard Worker }
348*c8dee2aaSAndroid Build Coastguard Worker private:
349*c8dee2aaSAndroid Build Coastguard Worker static const int kScratchKeyFieldCnt = 6;
350*c8dee2aaSAndroid Build Coastguard Worker
TestResource(GrGpu * gpu,skgpu::Budgeted budgeted,SimulatedProperty property,ScratchConstructor,std::string_view label,size_t size=kDefaultSize)351*c8dee2aaSAndroid Build Coastguard Worker TestResource(GrGpu* gpu,
352*c8dee2aaSAndroid Build Coastguard Worker skgpu::Budgeted budgeted,
353*c8dee2aaSAndroid Build Coastguard Worker SimulatedProperty property,
354*c8dee2aaSAndroid Build Coastguard Worker ScratchConstructor,
355*c8dee2aaSAndroid Build Coastguard Worker std::string_view label,
356*c8dee2aaSAndroid Build Coastguard Worker size_t size = kDefaultSize)
357*c8dee2aaSAndroid Build Coastguard Worker : INHERITED(gpu, label)
358*c8dee2aaSAndroid Build Coastguard Worker , fToDelete(nullptr)
359*c8dee2aaSAndroid Build Coastguard Worker , fSize(size)
360*c8dee2aaSAndroid Build Coastguard Worker , fProperty(property)
361*c8dee2aaSAndroid Build Coastguard Worker , fIsScratch(true) {
362*c8dee2aaSAndroid Build Coastguard Worker ++fNumAlive;
363*c8dee2aaSAndroid Build Coastguard Worker this->registerWithCache(budgeted);
364*c8dee2aaSAndroid Build Coastguard Worker }
365*c8dee2aaSAndroid Build Coastguard Worker
366*c8dee2aaSAndroid Build Coastguard Worker // Constructor for simulating resources that wrap backend objects.
TestResource(GrGpu * gpu,GrWrapCacheable cacheable,size_t size,std::string_view label)367*c8dee2aaSAndroid Build Coastguard Worker TestResource(GrGpu* gpu, GrWrapCacheable cacheable, size_t size, std::string_view label)
368*c8dee2aaSAndroid Build Coastguard Worker : INHERITED(gpu, label)
369*c8dee2aaSAndroid Build Coastguard Worker , fToDelete(nullptr)
370*c8dee2aaSAndroid Build Coastguard Worker , fSize(size)
371*c8dee2aaSAndroid Build Coastguard Worker , fProperty(kA_SimulatedProperty)
372*c8dee2aaSAndroid Build Coastguard Worker , fIsScratch(false) {
373*c8dee2aaSAndroid Build Coastguard Worker ++fNumAlive;
374*c8dee2aaSAndroid Build Coastguard Worker this->registerWithCacheWrapped(cacheable);
375*c8dee2aaSAndroid Build Coastguard Worker }
376*c8dee2aaSAndroid Build Coastguard Worker
computeScratchKey(skgpu::ScratchKey * key) const377*c8dee2aaSAndroid Build Coastguard Worker void computeScratchKey(skgpu::ScratchKey* key) const override {
378*c8dee2aaSAndroid Build Coastguard Worker if (fIsScratch) {
379*c8dee2aaSAndroid Build Coastguard Worker ComputeScratchKey(fProperty, key);
380*c8dee2aaSAndroid Build Coastguard Worker }
381*c8dee2aaSAndroid Build Coastguard Worker }
382*c8dee2aaSAndroid Build Coastguard Worker
onGpuMemorySize() const383*c8dee2aaSAndroid Build Coastguard Worker size_t onGpuMemorySize() const override { return fSize; }
onSetLabel()384*c8dee2aaSAndroid Build Coastguard Worker void onSetLabel() override{}
getResourceType() const385*c8dee2aaSAndroid Build Coastguard Worker const char* getResourceType() const override { return "Test"; }
386*c8dee2aaSAndroid Build Coastguard Worker
387*c8dee2aaSAndroid Build Coastguard Worker sk_sp<TestResource> fToDelete;
388*c8dee2aaSAndroid Build Coastguard Worker size_t fSize;
389*c8dee2aaSAndroid Build Coastguard Worker static int fNumAlive;
390*c8dee2aaSAndroid Build Coastguard Worker SimulatedProperty fProperty;
391*c8dee2aaSAndroid Build Coastguard Worker bool fIsScratch;
392*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = GrGpuResource;
393*c8dee2aaSAndroid Build Coastguard Worker };
394*c8dee2aaSAndroid Build Coastguard Worker int TestResource::fNumAlive = 0;
395*c8dee2aaSAndroid Build Coastguard Worker
396*c8dee2aaSAndroid Build Coastguard Worker class Mock {
397*c8dee2aaSAndroid Build Coastguard Worker public:
Mock(size_t maxBytes)398*c8dee2aaSAndroid Build Coastguard Worker Mock(size_t maxBytes) {
399*c8dee2aaSAndroid Build Coastguard Worker fDContext = GrDirectContext::MakeMock(nullptr);
400*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fDContext);
401*c8dee2aaSAndroid Build Coastguard Worker fDContext->setResourceCacheLimit(maxBytes);
402*c8dee2aaSAndroid Build Coastguard Worker GrResourceCache* cache = fDContext->priv().getResourceCache();
403*c8dee2aaSAndroid Build Coastguard Worker cache->purgeUnlockedResources(GrPurgeResourceOptions::kAllResources);
404*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(0 == cache->getResourceCount() && 0 == cache->getResourceBytes());
405*c8dee2aaSAndroid Build Coastguard Worker }
406*c8dee2aaSAndroid Build Coastguard Worker
cache()407*c8dee2aaSAndroid Build Coastguard Worker GrResourceCache* cache() { return fDContext->priv().getResourceCache(); }
gpu()408*c8dee2aaSAndroid Build Coastguard Worker GrGpu* gpu() { return fDContext->priv().getGpu(); }
dContext()409*c8dee2aaSAndroid Build Coastguard Worker GrDirectContext* dContext() { return fDContext.get(); }
410*c8dee2aaSAndroid Build Coastguard Worker
reset()411*c8dee2aaSAndroid Build Coastguard Worker void reset() {
412*c8dee2aaSAndroid Build Coastguard Worker fDContext.reset();
413*c8dee2aaSAndroid Build Coastguard Worker }
414*c8dee2aaSAndroid Build Coastguard Worker
415*c8dee2aaSAndroid Build Coastguard Worker private:
416*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrDirectContext> fDContext;
417*c8dee2aaSAndroid Build Coastguard Worker };
418*c8dee2aaSAndroid Build Coastguard Worker
test_no_key(skiatest::Reporter * reporter)419*c8dee2aaSAndroid Build Coastguard Worker static void test_no_key(skiatest::Reporter* reporter) {
420*c8dee2aaSAndroid Build Coastguard Worker Mock mock(30000);
421*c8dee2aaSAndroid Build Coastguard Worker GrResourceCache* cache = mock.cache();
422*c8dee2aaSAndroid Build Coastguard Worker GrGpu* gpu = mock.gpu();
423*c8dee2aaSAndroid Build Coastguard Worker
424*c8dee2aaSAndroid Build Coastguard Worker // Create a bunch of resources with no keys
425*c8dee2aaSAndroid Build Coastguard Worker TestResource* a = new TestResource(gpu, /*label=*/{}, skgpu::Budgeted::kYes, 11);
426*c8dee2aaSAndroid Build Coastguard Worker TestResource* b = new TestResource(gpu, /*label=*/{}, skgpu::Budgeted::kYes, 12);
427*c8dee2aaSAndroid Build Coastguard Worker TestResource* c = new TestResource(gpu, /*label=*/{}, skgpu::Budgeted::kYes, 13);
428*c8dee2aaSAndroid Build Coastguard Worker TestResource* d = new TestResource(gpu, /*label=*/{}, skgpu::Budgeted::kYes, 14);
429*c8dee2aaSAndroid Build Coastguard Worker
430*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 4 == TestResource::NumAlive());
431*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 4 == cache->getResourceCount());
432*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() + c->gpuMemorySize() +
433*c8dee2aaSAndroid Build Coastguard Worker d->gpuMemorySize() == cache->getResourceBytes());
434*c8dee2aaSAndroid Build Coastguard Worker
435*c8dee2aaSAndroid Build Coastguard Worker // Should be safe to purge without deleting the resources since we still have refs.
436*c8dee2aaSAndroid Build Coastguard Worker cache->purgeUnlockedResources(GrPurgeResourceOptions::kAllResources);
437*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 4 == TestResource::NumAlive());
438*c8dee2aaSAndroid Build Coastguard Worker
439*c8dee2aaSAndroid Build Coastguard Worker // Since the resources have neither unique nor scratch keys, delete immediately upon unref.
440*c8dee2aaSAndroid Build Coastguard Worker
441*c8dee2aaSAndroid Build Coastguard Worker a->unref();
442*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 3 == TestResource::NumAlive());
443*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
444*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, b->gpuMemorySize() + c->gpuMemorySize() + d->gpuMemorySize() ==
445*c8dee2aaSAndroid Build Coastguard Worker cache->getResourceBytes());
446*c8dee2aaSAndroid Build Coastguard Worker
447*c8dee2aaSAndroid Build Coastguard Worker c->unref();
448*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
449*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
450*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, b->gpuMemorySize() + d->gpuMemorySize() ==
451*c8dee2aaSAndroid Build Coastguard Worker cache->getResourceBytes());
452*c8dee2aaSAndroid Build Coastguard Worker
453*c8dee2aaSAndroid Build Coastguard Worker d->unref();
454*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
455*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
456*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, b->gpuMemorySize() == cache->getResourceBytes());
457*c8dee2aaSAndroid Build Coastguard Worker
458*c8dee2aaSAndroid Build Coastguard Worker b->unref();
459*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
460*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
461*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
462*c8dee2aaSAndroid Build Coastguard Worker }
463*c8dee2aaSAndroid Build Coastguard Worker
464*c8dee2aaSAndroid Build Coastguard Worker // Each integer passed as a template param creates a new domain.
465*c8dee2aaSAndroid Build Coastguard Worker template <int>
make_unique_key(skgpu::UniqueKey * key,int data,const char * tag=nullptr)466*c8dee2aaSAndroid Build Coastguard Worker static void make_unique_key(skgpu::UniqueKey* key, int data, const char* tag = nullptr) {
467*c8dee2aaSAndroid Build Coastguard Worker static skgpu::UniqueKey::Domain d = skgpu::UniqueKey::GenerateDomain();
468*c8dee2aaSAndroid Build Coastguard Worker skgpu::UniqueKey::Builder builder(key, d, 1, tag);
469*c8dee2aaSAndroid Build Coastguard Worker builder[0] = data;
470*c8dee2aaSAndroid Build Coastguard Worker }
471*c8dee2aaSAndroid Build Coastguard Worker
test_purge_unlocked(skiatest::Reporter * reporter)472*c8dee2aaSAndroid Build Coastguard Worker static void test_purge_unlocked(skiatest::Reporter* reporter) {
473*c8dee2aaSAndroid Build Coastguard Worker Mock mock(30000);
474*c8dee2aaSAndroid Build Coastguard Worker GrResourceCache* cache = mock.cache();
475*c8dee2aaSAndroid Build Coastguard Worker GrGpu* gpu = mock.gpu();
476*c8dee2aaSAndroid Build Coastguard Worker
477*c8dee2aaSAndroid Build Coastguard Worker // Create two resource w/ a unique key and two w/o but all of which have scratch keys.
478*c8dee2aaSAndroid Build Coastguard Worker TestResource* a = TestResource::CreateScratch(
479*c8dee2aaSAndroid Build Coastguard Worker gpu, skgpu::Budgeted::kYes, TestResource::kA_SimulatedProperty, 11);
480*c8dee2aaSAndroid Build Coastguard Worker
481*c8dee2aaSAndroid Build Coastguard Worker skgpu::UniqueKey uniqueKey;
482*c8dee2aaSAndroid Build Coastguard Worker make_unique_key<0>(&uniqueKey, 0);
483*c8dee2aaSAndroid Build Coastguard Worker
484*c8dee2aaSAndroid Build Coastguard Worker TestResource* b = TestResource::CreateScratch(
485*c8dee2aaSAndroid Build Coastguard Worker gpu, skgpu::Budgeted::kYes, TestResource::kA_SimulatedProperty, 12);
486*c8dee2aaSAndroid Build Coastguard Worker b->resourcePriv().setUniqueKey(uniqueKey);
487*c8dee2aaSAndroid Build Coastguard Worker
488*c8dee2aaSAndroid Build Coastguard Worker TestResource* c = TestResource::CreateScratch(
489*c8dee2aaSAndroid Build Coastguard Worker gpu, skgpu::Budgeted::kYes, TestResource::kA_SimulatedProperty, 13);
490*c8dee2aaSAndroid Build Coastguard Worker
491*c8dee2aaSAndroid Build Coastguard Worker skgpu::UniqueKey uniqueKey2;
492*c8dee2aaSAndroid Build Coastguard Worker make_unique_key<0>(&uniqueKey2, 1);
493*c8dee2aaSAndroid Build Coastguard Worker
494*c8dee2aaSAndroid Build Coastguard Worker TestResource* d = TestResource::CreateScratch(
495*c8dee2aaSAndroid Build Coastguard Worker gpu, skgpu::Budgeted::kYes, TestResource::kA_SimulatedProperty, 14);
496*c8dee2aaSAndroid Build Coastguard Worker d->resourcePriv().setUniqueKey(uniqueKey2);
497*c8dee2aaSAndroid Build Coastguard Worker
498*c8dee2aaSAndroid Build Coastguard Worker
499*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 4 == TestResource::NumAlive());
500*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 4 == cache->getResourceCount());
501*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() + c->gpuMemorySize() +
502*c8dee2aaSAndroid Build Coastguard Worker d->gpuMemorySize() == cache->getResourceBytes());
503*c8dee2aaSAndroid Build Coastguard Worker
504*c8dee2aaSAndroid Build Coastguard Worker // Should be safe to purge without deleting the resources since we still have refs.
505*c8dee2aaSAndroid Build Coastguard Worker cache->purgeUnlockedResources(GrPurgeResourceOptions::kAllResources);
506*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 4 == TestResource::NumAlive());
507*c8dee2aaSAndroid Build Coastguard Worker
508*c8dee2aaSAndroid Build Coastguard Worker // Unref them all. Since they all have keys they should remain in the cache.
509*c8dee2aaSAndroid Build Coastguard Worker
510*c8dee2aaSAndroid Build Coastguard Worker a->unref();
511*c8dee2aaSAndroid Build Coastguard Worker b->unref();
512*c8dee2aaSAndroid Build Coastguard Worker c->unref();
513*c8dee2aaSAndroid Build Coastguard Worker d->unref();
514*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 4 == TestResource::NumAlive());
515*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 4 == cache->getResourceCount());
516*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() + c->gpuMemorySize() +
517*c8dee2aaSAndroid Build Coastguard Worker d->gpuMemorySize() == cache->getResourceBytes());
518*c8dee2aaSAndroid Build Coastguard Worker
519*c8dee2aaSAndroid Build Coastguard Worker // Purge only the two scratch resources
520*c8dee2aaSAndroid Build Coastguard Worker cache->purgeUnlockedResources(GrPurgeResourceOptions::kScratchResourcesOnly);
521*c8dee2aaSAndroid Build Coastguard Worker
522*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
523*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
524*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, b->gpuMemorySize() + d->gpuMemorySize() ==
525*c8dee2aaSAndroid Build Coastguard Worker cache->getResourceBytes());
526*c8dee2aaSAndroid Build Coastguard Worker
527*c8dee2aaSAndroid Build Coastguard Worker // Purge the uniquely keyed resources
528*c8dee2aaSAndroid Build Coastguard Worker cache->purgeUnlockedResources(GrPurgeResourceOptions::kAllResources);
529*c8dee2aaSAndroid Build Coastguard Worker
530*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
531*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
532*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
533*c8dee2aaSAndroid Build Coastguard Worker }
534*c8dee2aaSAndroid Build Coastguard Worker
test_purge_command_buffer_usage(skiatest::Reporter * reporter)535*c8dee2aaSAndroid Build Coastguard Worker static void test_purge_command_buffer_usage(skiatest::Reporter* reporter) {
536*c8dee2aaSAndroid Build Coastguard Worker Mock mock(30000);
537*c8dee2aaSAndroid Build Coastguard Worker GrResourceCache* cache = mock.cache();
538*c8dee2aaSAndroid Build Coastguard Worker GrGpu* gpu = mock.gpu();
539*c8dee2aaSAndroid Build Coastguard Worker
540*c8dee2aaSAndroid Build Coastguard Worker // Create two resource w/ scratch keys.
541*c8dee2aaSAndroid Build Coastguard Worker TestResource* a = TestResource::CreateScratch(
542*c8dee2aaSAndroid Build Coastguard Worker gpu, skgpu::Budgeted::kYes, TestResource::kA_SimulatedProperty, 11);
543*c8dee2aaSAndroid Build Coastguard Worker
544*c8dee2aaSAndroid Build Coastguard Worker TestResource* b = TestResource::CreateScratch(
545*c8dee2aaSAndroid Build Coastguard Worker gpu, skgpu::Budgeted::kYes, TestResource::kA_SimulatedProperty, 12);
546*c8dee2aaSAndroid Build Coastguard Worker
547*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
548*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
549*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() == cache->getResourceBytes());
550*c8dee2aaSAndroid Build Coastguard Worker
551*c8dee2aaSAndroid Build Coastguard Worker // Should be safe to purge without deleting the resources since we still have refs.
552*c8dee2aaSAndroid Build Coastguard Worker cache->purgeUnlockedResources(GrPurgeResourceOptions::kScratchResourcesOnly);
553*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
554*c8dee2aaSAndroid Build Coastguard Worker
555*c8dee2aaSAndroid Build Coastguard Worker // Add command buffer usages to all resources
556*c8dee2aaSAndroid Build Coastguard Worker a->refCommandBuffer();
557*c8dee2aaSAndroid Build Coastguard Worker b->refCommandBuffer();
558*c8dee2aaSAndroid Build Coastguard Worker
559*c8dee2aaSAndroid Build Coastguard Worker // Should be safe to purge without deleting the resources since we still have refs and command
560*c8dee2aaSAndroid Build Coastguard Worker // buffer usages.
561*c8dee2aaSAndroid Build Coastguard Worker cache->purgeUnlockedResources(GrPurgeResourceOptions::kScratchResourcesOnly);
562*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
563*c8dee2aaSAndroid Build Coastguard Worker
564*c8dee2aaSAndroid Build Coastguard Worker // Unref the first resource
565*c8dee2aaSAndroid Build Coastguard Worker a->unref();
566*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
567*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
568*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() == cache->getResourceBytes());
569*c8dee2aaSAndroid Build Coastguard Worker
570*c8dee2aaSAndroid Build Coastguard Worker // Should be safe to purge without deleting the resources since we still have command buffer
571*c8dee2aaSAndroid Build Coastguard Worker // usages and the second still has a ref.
572*c8dee2aaSAndroid Build Coastguard Worker cache->purgeUnlockedResources(GrPurgeResourceOptions::kScratchResourcesOnly);
573*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
574*c8dee2aaSAndroid Build Coastguard Worker
575*c8dee2aaSAndroid Build Coastguard Worker // Remove command buffer usages
576*c8dee2aaSAndroid Build Coastguard Worker a->unrefCommandBuffer();
577*c8dee2aaSAndroid Build Coastguard Worker b->unrefCommandBuffer();
578*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
579*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
580*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() == cache->getResourceBytes());
581*c8dee2aaSAndroid Build Coastguard Worker
582*c8dee2aaSAndroid Build Coastguard Worker // Purge this time should remove the first resources since it no longer has any refs or command
583*c8dee2aaSAndroid Build Coastguard Worker // buffer usages.
584*c8dee2aaSAndroid Build Coastguard Worker cache->purgeUnlockedResources(GrPurgeResourceOptions::kScratchResourcesOnly);
585*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
586*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
587*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, b->gpuMemorySize() == cache->getResourceBytes());
588*c8dee2aaSAndroid Build Coastguard Worker
589*c8dee2aaSAndroid Build Coastguard Worker // Unref the second resource
590*c8dee2aaSAndroid Build Coastguard Worker b->unref();
591*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
592*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
593*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, b->gpuMemorySize() == cache->getResourceBytes());
594*c8dee2aaSAndroid Build Coastguard Worker
595*c8dee2aaSAndroid Build Coastguard Worker // Purge the last resource
596*c8dee2aaSAndroid Build Coastguard Worker cache->purgeUnlockedResources(GrPurgeResourceOptions::kAllResources);
597*c8dee2aaSAndroid Build Coastguard Worker
598*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
599*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
600*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
601*c8dee2aaSAndroid Build Coastguard Worker }
602*c8dee2aaSAndroid Build Coastguard Worker
test_budgeting(skiatest::Reporter * reporter)603*c8dee2aaSAndroid Build Coastguard Worker static void test_budgeting(skiatest::Reporter* reporter) {
604*c8dee2aaSAndroid Build Coastguard Worker Mock mock(300);
605*c8dee2aaSAndroid Build Coastguard Worker GrResourceCache* cache = mock.cache();
606*c8dee2aaSAndroid Build Coastguard Worker GrGpu* gpu = mock.gpu();
607*c8dee2aaSAndroid Build Coastguard Worker
608*c8dee2aaSAndroid Build Coastguard Worker skgpu::UniqueKey uniqueKey;
609*c8dee2aaSAndroid Build Coastguard Worker make_unique_key<0>(&uniqueKey, 0);
610*c8dee2aaSAndroid Build Coastguard Worker
611*c8dee2aaSAndroid Build Coastguard Worker // Create a scratch, a unique, and a wrapped resource
612*c8dee2aaSAndroid Build Coastguard Worker TestResource* scratch = TestResource::CreateScratch(
613*c8dee2aaSAndroid Build Coastguard Worker gpu, skgpu::Budgeted::kYes, TestResource::kB_SimulatedProperty, 10);
614*c8dee2aaSAndroid Build Coastguard Worker TestResource* unique = new TestResource(gpu, /*label=*/{}, skgpu::Budgeted::kYes, 11);
615*c8dee2aaSAndroid Build Coastguard Worker unique->resourcePriv().setUniqueKey(uniqueKey);
616*c8dee2aaSAndroid Build Coastguard Worker TestResource* wrappedCacheable = TestResource::CreateWrapped(gpu, GrWrapCacheable::kYes, 12);
617*c8dee2aaSAndroid Build Coastguard Worker TestResource* wrappedUncacheable = TestResource::CreateWrapped(gpu, GrWrapCacheable::kNo, 13);
618*c8dee2aaSAndroid Build Coastguard Worker TestResource* unbudgeted = new TestResource(gpu, /*label=*/{}, skgpu::Budgeted::kNo, 14);
619*c8dee2aaSAndroid Build Coastguard Worker
620*c8dee2aaSAndroid Build Coastguard Worker // Make sure we can add a unique key to the wrapped resources
621*c8dee2aaSAndroid Build Coastguard Worker skgpu::UniqueKey uniqueKey2;
622*c8dee2aaSAndroid Build Coastguard Worker make_unique_key<0>(&uniqueKey2, 1);
623*c8dee2aaSAndroid Build Coastguard Worker skgpu::UniqueKey uniqueKey3;
624*c8dee2aaSAndroid Build Coastguard Worker make_unique_key<0>(&uniqueKey3, 2);
625*c8dee2aaSAndroid Build Coastguard Worker wrappedCacheable->resourcePriv().setUniqueKey(uniqueKey2);
626*c8dee2aaSAndroid Build Coastguard Worker wrappedUncacheable->resourcePriv().setUniqueKey(uniqueKey3);
627*c8dee2aaSAndroid Build Coastguard Worker GrGpuResource* wrappedCacheableViaKey = cache->findAndRefUniqueResource(uniqueKey2);
628*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, wrappedCacheableViaKey);
629*c8dee2aaSAndroid Build Coastguard Worker GrGpuResource* wrappedUncacheableViaKey = cache->findAndRefUniqueResource(uniqueKey3);
630*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, wrappedUncacheableViaKey);
631*c8dee2aaSAndroid Build Coastguard Worker
632*c8dee2aaSAndroid Build Coastguard Worker // Remove the extra refs we just added.
633*c8dee2aaSAndroid Build Coastguard Worker SkSafeUnref(wrappedCacheableViaKey);
634*c8dee2aaSAndroid Build Coastguard Worker SkSafeUnref(wrappedUncacheableViaKey);
635*c8dee2aaSAndroid Build Coastguard Worker
636*c8dee2aaSAndroid Build Coastguard Worker // Make sure sizes are as we expect
637*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 5 == cache->getResourceCount());
638*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() +
639*c8dee2aaSAndroid Build Coastguard Worker wrappedCacheable->gpuMemorySize() +
640*c8dee2aaSAndroid Build Coastguard Worker wrappedUncacheable->gpuMemorySize() +
641*c8dee2aaSAndroid Build Coastguard Worker unbudgeted->gpuMemorySize() ==
642*c8dee2aaSAndroid Build Coastguard Worker cache->getResourceBytes());
643*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
644*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() ==
645*c8dee2aaSAndroid Build Coastguard Worker cache->getBudgetedResourceBytes());
646*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
647*c8dee2aaSAndroid Build Coastguard Worker
648*c8dee2aaSAndroid Build Coastguard Worker // Our refs mean that the resources are non purgeable.
649*c8dee2aaSAndroid Build Coastguard Worker cache->purgeUnlockedResources(GrPurgeResourceOptions::kAllResources);
650*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 5 == cache->getResourceCount());
651*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() +
652*c8dee2aaSAndroid Build Coastguard Worker wrappedCacheable->gpuMemorySize() +
653*c8dee2aaSAndroid Build Coastguard Worker wrappedUncacheable->gpuMemorySize() +
654*c8dee2aaSAndroid Build Coastguard Worker unbudgeted->gpuMemorySize() ==
655*c8dee2aaSAndroid Build Coastguard Worker cache->getResourceBytes());
656*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
657*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() ==
658*c8dee2aaSAndroid Build Coastguard Worker cache->getBudgetedResourceBytes());
659*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
660*c8dee2aaSAndroid Build Coastguard Worker
661*c8dee2aaSAndroid Build Coastguard Worker // Unreffing the cacheable wrapped resource with a unique key shouldn't free it right away.
662*c8dee2aaSAndroid Build Coastguard Worker // However, unreffing the uncacheable wrapped resource should free it.
663*c8dee2aaSAndroid Build Coastguard Worker wrappedCacheable->unref();
664*c8dee2aaSAndroid Build Coastguard Worker wrappedUncacheable->unref();
665*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 4 == cache->getResourceCount());
666*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() +
667*c8dee2aaSAndroid Build Coastguard Worker wrappedCacheable->gpuMemorySize() +
668*c8dee2aaSAndroid Build Coastguard Worker unbudgeted->gpuMemorySize() ==
669*c8dee2aaSAndroid Build Coastguard Worker cache->getResourceBytes());
670*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
671*c8dee2aaSAndroid Build Coastguard Worker
672*c8dee2aaSAndroid Build Coastguard Worker // Now try freeing the budgeted resources first
673*c8dee2aaSAndroid Build Coastguard Worker wrappedUncacheable = TestResource::CreateWrapped(gpu, GrWrapCacheable::kNo);
674*c8dee2aaSAndroid Build Coastguard Worker unique->unref();
675*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 11 == cache->getPurgeableBytes());
676*c8dee2aaSAndroid Build Coastguard Worker // This will free 'unique' but not wrappedCacheable which has a key. That requires the key to be
677*c8dee2aaSAndroid Build Coastguard Worker // removed to be freed.
678*c8dee2aaSAndroid Build Coastguard Worker cache->purgeUnlockedResources(GrPurgeResourceOptions::kAllResources);
679*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 4 == cache->getResourceCount());
680*c8dee2aaSAndroid Build Coastguard Worker
681*c8dee2aaSAndroid Build Coastguard Worker wrappedCacheableViaKey = cache->findAndRefUniqueResource(uniqueKey2);
682*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, wrappedCacheableViaKey);
683*c8dee2aaSAndroid Build Coastguard Worker if (wrappedCacheableViaKey) {
684*c8dee2aaSAndroid Build Coastguard Worker wrappedCacheableViaKey->resourcePriv().removeUniqueKey();
685*c8dee2aaSAndroid Build Coastguard Worker wrappedCacheable->unref();
686*c8dee2aaSAndroid Build Coastguard Worker }
687*c8dee2aaSAndroid Build Coastguard Worker // We shouldn't have to call purgeAllUnlocked as removing the key on a wrapped cacheable
688*c8dee2aaSAndroid Build Coastguard Worker // resource should immediately delete it.
689*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
690*c8dee2aaSAndroid Build Coastguard Worker
691*c8dee2aaSAndroid Build Coastguard Worker wrappedCacheable = TestResource::CreateWrapped(gpu, GrWrapCacheable::kYes);
692*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + wrappedCacheable->gpuMemorySize() +
693*c8dee2aaSAndroid Build Coastguard Worker wrappedUncacheable->gpuMemorySize() +
694*c8dee2aaSAndroid Build Coastguard Worker unbudgeted->gpuMemorySize() ==
695*c8dee2aaSAndroid Build Coastguard Worker cache->getResourceBytes());
696*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == cache->getBudgetedResourceCount());
697*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, scratch->gpuMemorySize() == cache->getBudgetedResourceBytes());
698*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
699*c8dee2aaSAndroid Build Coastguard Worker
700*c8dee2aaSAndroid Build Coastguard Worker scratch->unref();
701*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 10 == cache->getPurgeableBytes());
702*c8dee2aaSAndroid Build Coastguard Worker cache->purgeUnlockedResources(GrPurgeResourceOptions::kAllResources);
703*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
704*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, unbudgeted->gpuMemorySize() + wrappedCacheable->gpuMemorySize() +
705*c8dee2aaSAndroid Build Coastguard Worker wrappedUncacheable->gpuMemorySize() ==
706*c8dee2aaSAndroid Build Coastguard Worker cache->getResourceBytes());
707*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
708*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
709*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
710*c8dee2aaSAndroid Build Coastguard Worker
711*c8dee2aaSAndroid Build Coastguard Worker // Unreffing the wrapped resources (with no unique key) should free them right away.
712*c8dee2aaSAndroid Build Coastguard Worker wrappedUncacheable->unref();
713*c8dee2aaSAndroid Build Coastguard Worker wrappedCacheable->unref();
714*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
715*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, unbudgeted->gpuMemorySize() == cache->getResourceBytes());
716*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
717*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
718*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
719*c8dee2aaSAndroid Build Coastguard Worker
720*c8dee2aaSAndroid Build Coastguard Worker unbudgeted->unref();
721*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
722*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
723*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
724*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
725*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
726*c8dee2aaSAndroid Build Coastguard Worker }
727*c8dee2aaSAndroid Build Coastguard Worker
test_unbudgeted(skiatest::Reporter * reporter)728*c8dee2aaSAndroid Build Coastguard Worker static void test_unbudgeted(skiatest::Reporter* reporter) {
729*c8dee2aaSAndroid Build Coastguard Worker Mock mock(30000);
730*c8dee2aaSAndroid Build Coastguard Worker GrResourceCache* cache = mock.cache();
731*c8dee2aaSAndroid Build Coastguard Worker GrGpu* gpu = mock.gpu();
732*c8dee2aaSAndroid Build Coastguard Worker
733*c8dee2aaSAndroid Build Coastguard Worker skgpu::UniqueKey uniqueKey;
734*c8dee2aaSAndroid Build Coastguard Worker make_unique_key<0>(&uniqueKey, 0);
735*c8dee2aaSAndroid Build Coastguard Worker
736*c8dee2aaSAndroid Build Coastguard Worker TestResource* scratch;
737*c8dee2aaSAndroid Build Coastguard Worker TestResource* unique;
738*c8dee2aaSAndroid Build Coastguard Worker TestResource* wrapped;
739*c8dee2aaSAndroid Build Coastguard Worker TestResource* unbudgeted;
740*c8dee2aaSAndroid Build Coastguard Worker
741*c8dee2aaSAndroid Build Coastguard Worker // A large uncached or wrapped resource shouldn't evict anything.
742*c8dee2aaSAndroid Build Coastguard Worker scratch = TestResource::CreateScratch(
743*c8dee2aaSAndroid Build Coastguard Worker gpu, skgpu::Budgeted::kYes, TestResource::kB_SimulatedProperty, 10);
744*c8dee2aaSAndroid Build Coastguard Worker
745*c8dee2aaSAndroid Build Coastguard Worker scratch->unref();
746*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
747*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 10 == cache->getResourceBytes());
748*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == cache->getBudgetedResourceCount());
749*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 10 == cache->getBudgetedResourceBytes());
750*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 10 == cache->getPurgeableBytes());
751*c8dee2aaSAndroid Build Coastguard Worker
752*c8dee2aaSAndroid Build Coastguard Worker unique = new TestResource(gpu, /*label=*/{}, skgpu::Budgeted::kYes, 11);
753*c8dee2aaSAndroid Build Coastguard Worker unique->resourcePriv().setUniqueKey(uniqueKey);
754*c8dee2aaSAndroid Build Coastguard Worker unique->unref();
755*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
756*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 21 == cache->getResourceBytes());
757*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
758*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
759*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 21 == cache->getPurgeableBytes());
760*c8dee2aaSAndroid Build Coastguard Worker
761*c8dee2aaSAndroid Build Coastguard Worker size_t large = 2 * cache->getResourceBytes();
762*c8dee2aaSAndroid Build Coastguard Worker unbudgeted = new TestResource(gpu, /*label=*/{}, skgpu::Budgeted::kNo, large);
763*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
764*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 21 + large == cache->getResourceBytes());
765*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
766*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
767*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 21 == cache->getPurgeableBytes());
768*c8dee2aaSAndroid Build Coastguard Worker
769*c8dee2aaSAndroid Build Coastguard Worker unbudgeted->unref();
770*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
771*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 21 == cache->getResourceBytes());
772*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
773*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
774*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 21 == cache->getPurgeableBytes());
775*c8dee2aaSAndroid Build Coastguard Worker
776*c8dee2aaSAndroid Build Coastguard Worker wrapped = TestResource::CreateWrapped(gpu, GrWrapCacheable::kYes, large);
777*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
778*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 21 + large == cache->getResourceBytes());
779*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
780*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
781*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 21 == cache->getPurgeableBytes());
782*c8dee2aaSAndroid Build Coastguard Worker
783*c8dee2aaSAndroid Build Coastguard Worker wrapped->unref();
784*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
785*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 21 == cache->getResourceBytes());
786*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
787*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
788*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 21 == cache->getPurgeableBytes());
789*c8dee2aaSAndroid Build Coastguard Worker
790*c8dee2aaSAndroid Build Coastguard Worker cache->purgeUnlockedResources(GrPurgeResourceOptions::kAllResources);
791*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
792*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
793*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
794*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
795*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
796*c8dee2aaSAndroid Build Coastguard Worker }
797*c8dee2aaSAndroid Build Coastguard Worker
798*c8dee2aaSAndroid Build Coastguard Worker // This method can't be static because it needs to friended in GrGpuResource::CacheAccess.
799*c8dee2aaSAndroid Build Coastguard Worker void test_unbudgeted_to_scratch(skiatest::Reporter* reporter);
test_unbudgeted_to_scratch(skiatest::Reporter * reporter)800*c8dee2aaSAndroid Build Coastguard Worker /*static*/ void test_unbudgeted_to_scratch(skiatest::Reporter* reporter) {
801*c8dee2aaSAndroid Build Coastguard Worker Mock mock(300);
802*c8dee2aaSAndroid Build Coastguard Worker GrResourceCache* cache = mock.cache();
803*c8dee2aaSAndroid Build Coastguard Worker GrGpu* gpu = mock.gpu();
804*c8dee2aaSAndroid Build Coastguard Worker
805*c8dee2aaSAndroid Build Coastguard Worker TestResource* resource = TestResource::CreateScratch(
806*c8dee2aaSAndroid Build Coastguard Worker gpu, skgpu::Budgeted::kNo, TestResource::kA_SimulatedProperty);
807*c8dee2aaSAndroid Build Coastguard Worker skgpu::ScratchKey key;
808*c8dee2aaSAndroid Build Coastguard Worker TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &key);
809*c8dee2aaSAndroid Build Coastguard Worker
810*c8dee2aaSAndroid Build Coastguard Worker size_t size = resource->gpuMemorySize();
811*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 2; ++i) {
812*c8dee2aaSAndroid Build Coastguard Worker // Since this resource is unbudgeted, it should not be reachable as scratch.
813*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resource->resourcePriv().getScratchKey() == key);
814*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !resource->cacheAccess().isScratch());
815*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, GrBudgetedType::kUnbudgetedUncacheable ==
816*c8dee2aaSAndroid Build Coastguard Worker resource->resourcePriv().budgetedType());
817*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !cache->findAndRefScratchResource(key));
818*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
819*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, size == cache->getResourceBytes());
820*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
821*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
822*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
823*c8dee2aaSAndroid Build Coastguard Worker
824*c8dee2aaSAndroid Build Coastguard Worker // Once it is unrefed, it should become available as scratch.
825*c8dee2aaSAndroid Build Coastguard Worker resource->unref();
826*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
827*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, size == cache->getResourceBytes());
828*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == cache->getBudgetedResourceCount());
829*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, size == cache->getBudgetedResourceBytes());
830*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, size == cache->getPurgeableBytes());
831*c8dee2aaSAndroid Build Coastguard Worker resource = static_cast<TestResource*>(cache->findAndRefScratchResource(key));
832*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resource);
833*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resource->resourcePriv().getScratchKey() == key);
834*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resource->cacheAccess().isScratch());
835*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter,
836*c8dee2aaSAndroid Build Coastguard Worker GrBudgetedType::kBudgeted == resource->resourcePriv().budgetedType());
837*c8dee2aaSAndroid Build Coastguard Worker
838*c8dee2aaSAndroid Build Coastguard Worker if (0 == i) {
839*c8dee2aaSAndroid Build Coastguard Worker // If made unbudgeted, it should return to original state: ref'ed and unbudgeted. Try
840*c8dee2aaSAndroid Build Coastguard Worker // the above tests again.
841*c8dee2aaSAndroid Build Coastguard Worker resource->resourcePriv().makeUnbudgeted();
842*c8dee2aaSAndroid Build Coastguard Worker } else {
843*c8dee2aaSAndroid Build Coastguard Worker // After the second time around, try removing the scratch key
844*c8dee2aaSAndroid Build Coastguard Worker resource->resourcePriv().removeScratchKey();
845*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
846*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, size == cache->getResourceBytes());
847*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == cache->getBudgetedResourceCount());
848*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, size == cache->getBudgetedResourceBytes());
849*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
850*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !resource->resourcePriv().getScratchKey().isValid());
851*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !resource->cacheAccess().isScratch());
852*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter,
853*c8dee2aaSAndroid Build Coastguard Worker GrBudgetedType::kBudgeted == resource->resourcePriv().budgetedType());
854*c8dee2aaSAndroid Build Coastguard Worker
855*c8dee2aaSAndroid Build Coastguard Worker // now when it is unrefed it should die since it has no key.
856*c8dee2aaSAndroid Build Coastguard Worker resource->unref();
857*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
858*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
859*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
860*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
861*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
862*c8dee2aaSAndroid Build Coastguard Worker }
863*c8dee2aaSAndroid Build Coastguard Worker }
864*c8dee2aaSAndroid Build Coastguard Worker }
865*c8dee2aaSAndroid Build Coastguard Worker
test_duplicate_scratch_key(skiatest::Reporter * reporter)866*c8dee2aaSAndroid Build Coastguard Worker static void test_duplicate_scratch_key(skiatest::Reporter* reporter) {
867*c8dee2aaSAndroid Build Coastguard Worker Mock mock(30000);
868*c8dee2aaSAndroid Build Coastguard Worker GrResourceCache* cache = mock.cache();
869*c8dee2aaSAndroid Build Coastguard Worker GrGpu* gpu = mock.gpu();
870*c8dee2aaSAndroid Build Coastguard Worker
871*c8dee2aaSAndroid Build Coastguard Worker // Create two resources that have the same scratch key.
872*c8dee2aaSAndroid Build Coastguard Worker TestResource* a = TestResource::CreateScratch(
873*c8dee2aaSAndroid Build Coastguard Worker gpu, skgpu::Budgeted::kYes, TestResource::kB_SimulatedProperty, 11);
874*c8dee2aaSAndroid Build Coastguard Worker TestResource* b = TestResource::CreateScratch(
875*c8dee2aaSAndroid Build Coastguard Worker gpu, skgpu::Budgeted::kYes, TestResource::kB_SimulatedProperty, 12);
876*c8dee2aaSAndroid Build Coastguard Worker skgpu::ScratchKey scratchKey1;
877*c8dee2aaSAndroid Build Coastguard Worker TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey1);
878*c8dee2aaSAndroid Build Coastguard Worker // Check for negative case consistency. (leaks upon test failure.)
879*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !cache->findAndRefScratchResource(scratchKey1));
880*c8dee2aaSAndroid Build Coastguard Worker
881*c8dee2aaSAndroid Build Coastguard Worker skgpu::ScratchKey scratchKey;
882*c8dee2aaSAndroid Build Coastguard Worker TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey);
883*c8dee2aaSAndroid Build Coastguard Worker
884*c8dee2aaSAndroid Build Coastguard Worker // Scratch resources are registered with GrResourceCache just by existing. There are 2.
885*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
886*c8dee2aaSAndroid Build Coastguard Worker // As long as there are outstanding refs on the resources they will not be in the scratch map
887*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache->countScratchEntriesForKey(scratchKey));)
888*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
889*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() ==
890*c8dee2aaSAndroid Build Coastguard Worker cache->getResourceBytes());
891*c8dee2aaSAndroid Build Coastguard Worker
892*c8dee2aaSAndroid Build Coastguard Worker // Our refs mean that the resources are non purgeable.
893*c8dee2aaSAndroid Build Coastguard Worker cache->purgeUnlockedResources(GrPurgeResourceOptions::kAllResources);
894*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
895*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
896*c8dee2aaSAndroid Build Coastguard Worker
897*c8dee2aaSAndroid Build Coastguard Worker // Unref but don't purge
898*c8dee2aaSAndroid Build Coastguard Worker a->unref();
899*c8dee2aaSAndroid Build Coastguard Worker b->unref();
900*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
901*c8dee2aaSAndroid Build Coastguard Worker // Since we removed the refs to the resources they will now be in the scratch map
902*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(REPORTER_ASSERT(reporter, 2 == cache->countScratchEntriesForKey(scratchKey));)
903*c8dee2aaSAndroid Build Coastguard Worker
904*c8dee2aaSAndroid Build Coastguard Worker // Purge again. This time resources should be purgeable.
905*c8dee2aaSAndroid Build Coastguard Worker cache->purgeUnlockedResources(GrPurgeResourceOptions::kAllResources);
906*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
907*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
908*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache->countScratchEntriesForKey(scratchKey));)
909*c8dee2aaSAndroid Build Coastguard Worker }
910*c8dee2aaSAndroid Build Coastguard Worker
test_remove_scratch_key(skiatest::Reporter * reporter)911*c8dee2aaSAndroid Build Coastguard Worker static void test_remove_scratch_key(skiatest::Reporter* reporter) {
912*c8dee2aaSAndroid Build Coastguard Worker Mock mock(30000);
913*c8dee2aaSAndroid Build Coastguard Worker GrResourceCache* cache = mock.cache();
914*c8dee2aaSAndroid Build Coastguard Worker GrGpu* gpu = mock.gpu();
915*c8dee2aaSAndroid Build Coastguard Worker
916*c8dee2aaSAndroid Build Coastguard Worker // Create two resources that have the same scratch key.
917*c8dee2aaSAndroid Build Coastguard Worker TestResource* a = TestResource::CreateScratch(
918*c8dee2aaSAndroid Build Coastguard Worker gpu, skgpu::Budgeted::kYes, TestResource::kB_SimulatedProperty);
919*c8dee2aaSAndroid Build Coastguard Worker TestResource* b = TestResource::CreateScratch(
920*c8dee2aaSAndroid Build Coastguard Worker gpu, skgpu::Budgeted::kYes, TestResource::kB_SimulatedProperty);
921*c8dee2aaSAndroid Build Coastguard Worker a->unref();
922*c8dee2aaSAndroid Build Coastguard Worker b->unref();
923*c8dee2aaSAndroid Build Coastguard Worker
924*c8dee2aaSAndroid Build Coastguard Worker skgpu::ScratchKey scratchKey;
925*c8dee2aaSAndroid Build Coastguard Worker // Ensure that scratch key lookup is correct for negative case.
926*c8dee2aaSAndroid Build Coastguard Worker TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey);
927*c8dee2aaSAndroid Build Coastguard Worker // (following leaks upon test failure).
928*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !cache->findAndRefScratchResource(scratchKey));
929*c8dee2aaSAndroid Build Coastguard Worker
930*c8dee2aaSAndroid Build Coastguard Worker // Scratch resources are registered with GrResourceCache just by existing. There are 2.
931*c8dee2aaSAndroid Build Coastguard Worker TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey);
932*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
933*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(REPORTER_ASSERT(reporter, 2 == cache->countScratchEntriesForKey(scratchKey));)
934*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
935*c8dee2aaSAndroid Build Coastguard Worker
936*c8dee2aaSAndroid Build Coastguard Worker // Find the first resource and remove its scratch key
937*c8dee2aaSAndroid Build Coastguard Worker GrGpuResource* find = cache->findAndRefScratchResource(scratchKey);
938*c8dee2aaSAndroid Build Coastguard Worker find->resourcePriv().removeScratchKey();
939*c8dee2aaSAndroid Build Coastguard Worker // It's still alive, but not cached by scratch key anymore
940*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
941*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(REPORTER_ASSERT(reporter, 1 == cache->countScratchEntriesForKey(scratchKey));)
942*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
943*c8dee2aaSAndroid Build Coastguard Worker
944*c8dee2aaSAndroid Build Coastguard Worker // The cache should immediately delete it when it's unrefed since it isn't accessible.
945*c8dee2aaSAndroid Build Coastguard Worker find->unref();
946*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
947*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(REPORTER_ASSERT(reporter, 1 == cache->countScratchEntriesForKey(scratchKey));)
948*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
949*c8dee2aaSAndroid Build Coastguard Worker
950*c8dee2aaSAndroid Build Coastguard Worker // Repeat for the second resource.
951*c8dee2aaSAndroid Build Coastguard Worker find = cache->findAndRefScratchResource(scratchKey);
952*c8dee2aaSAndroid Build Coastguard Worker find->resourcePriv().removeScratchKey();
953*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
954*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache->countScratchEntriesForKey(scratchKey));)
955*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
956*c8dee2aaSAndroid Build Coastguard Worker
957*c8dee2aaSAndroid Build Coastguard Worker // Should be able to call this multiple times with no problem.
958*c8dee2aaSAndroid Build Coastguard Worker find->resourcePriv().removeScratchKey();
959*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
960*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache->countScratchEntriesForKey(scratchKey));)
961*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
962*c8dee2aaSAndroid Build Coastguard Worker
963*c8dee2aaSAndroid Build Coastguard Worker find->unref();
964*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
965*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache->countScratchEntriesForKey(scratchKey));)
966*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
967*c8dee2aaSAndroid Build Coastguard Worker }
968*c8dee2aaSAndroid Build Coastguard Worker
test_scratch_key_consistency(skiatest::Reporter * reporter)969*c8dee2aaSAndroid Build Coastguard Worker static void test_scratch_key_consistency(skiatest::Reporter* reporter) {
970*c8dee2aaSAndroid Build Coastguard Worker Mock mock(30000);
971*c8dee2aaSAndroid Build Coastguard Worker GrResourceCache* cache = mock.cache();
972*c8dee2aaSAndroid Build Coastguard Worker GrGpu* gpu = mock.gpu();
973*c8dee2aaSAndroid Build Coastguard Worker
974*c8dee2aaSAndroid Build Coastguard Worker // Create two resources that have the same scratch key.
975*c8dee2aaSAndroid Build Coastguard Worker TestResource* a = TestResource::CreateScratch(
976*c8dee2aaSAndroid Build Coastguard Worker gpu, skgpu::Budgeted::kYes, TestResource::kB_SimulatedProperty);
977*c8dee2aaSAndroid Build Coastguard Worker TestResource* b = TestResource::CreateScratch(
978*c8dee2aaSAndroid Build Coastguard Worker gpu, skgpu::Budgeted::kYes, TestResource::kB_SimulatedProperty);
979*c8dee2aaSAndroid Build Coastguard Worker a->unref();
980*c8dee2aaSAndroid Build Coastguard Worker b->unref();
981*c8dee2aaSAndroid Build Coastguard Worker
982*c8dee2aaSAndroid Build Coastguard Worker skgpu::ScratchKey scratchKey;
983*c8dee2aaSAndroid Build Coastguard Worker // Ensure that scratch key comparison and assignment is consistent.
984*c8dee2aaSAndroid Build Coastguard Worker skgpu::ScratchKey scratchKey1;
985*c8dee2aaSAndroid Build Coastguard Worker TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey1);
986*c8dee2aaSAndroid Build Coastguard Worker skgpu::ScratchKey scratchKey2;
987*c8dee2aaSAndroid Build Coastguard Worker TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey2);
988*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, scratchKey1.size() == TestResource::ExpectedScratchKeySize());
989*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, scratchKey1 != scratchKey2);
990*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, scratchKey2 != scratchKey1);
991*c8dee2aaSAndroid Build Coastguard Worker scratchKey = scratchKey1;
992*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, scratchKey.size() == TestResource::ExpectedScratchKeySize());
993*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, scratchKey1 == scratchKey);
994*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, scratchKey == scratchKey1);
995*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, scratchKey2 != scratchKey);
996*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, scratchKey != scratchKey2);
997*c8dee2aaSAndroid Build Coastguard Worker scratchKey = scratchKey2;
998*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, scratchKey.size() == TestResource::ExpectedScratchKeySize());
999*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, scratchKey1 != scratchKey);
1000*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, scratchKey != scratchKey1);
1001*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, scratchKey2 == scratchKey);
1002*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, scratchKey == scratchKey2);
1003*c8dee2aaSAndroid Build Coastguard Worker
1004*c8dee2aaSAndroid Build Coastguard Worker // Ensure that scratch key lookup is correct for negative case.
1005*c8dee2aaSAndroid Build Coastguard Worker TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey);
1006*c8dee2aaSAndroid Build Coastguard Worker // (following leaks upon test failure).
1007*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !cache->findAndRefScratchResource(scratchKey));
1008*c8dee2aaSAndroid Build Coastguard Worker
1009*c8dee2aaSAndroid Build Coastguard Worker // Find the first resource with a scratch key and a copy of a scratch key.
1010*c8dee2aaSAndroid Build Coastguard Worker TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey);
1011*c8dee2aaSAndroid Build Coastguard Worker GrGpuResource* find = cache->findAndRefScratchResource(scratchKey);
1012*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, find != nullptr);
1013*c8dee2aaSAndroid Build Coastguard Worker find->unref();
1014*c8dee2aaSAndroid Build Coastguard Worker
1015*c8dee2aaSAndroid Build Coastguard Worker scratchKey2 = scratchKey;
1016*c8dee2aaSAndroid Build Coastguard Worker find = cache->findAndRefScratchResource(scratchKey2);
1017*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, find != nullptr);
1018*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, find == a || find == b);
1019*c8dee2aaSAndroid Build Coastguard Worker
1020*c8dee2aaSAndroid Build Coastguard Worker GrGpuResource* find2 = cache->findAndRefScratchResource(scratchKey2);
1021*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, find2 != nullptr);
1022*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, find2 == a || find2 == b);
1023*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, find2 != find);
1024*c8dee2aaSAndroid Build Coastguard Worker find2->unref();
1025*c8dee2aaSAndroid Build Coastguard Worker find->unref();
1026*c8dee2aaSAndroid Build Coastguard Worker }
1027*c8dee2aaSAndroid Build Coastguard Worker
test_duplicate_unique_key(skiatest::Reporter * reporter)1028*c8dee2aaSAndroid Build Coastguard Worker static void test_duplicate_unique_key(skiatest::Reporter* reporter) {
1029*c8dee2aaSAndroid Build Coastguard Worker Mock mock(30000);
1030*c8dee2aaSAndroid Build Coastguard Worker GrResourceCache* cache = mock.cache();
1031*c8dee2aaSAndroid Build Coastguard Worker GrGpu* gpu = mock.gpu();
1032*c8dee2aaSAndroid Build Coastguard Worker
1033*c8dee2aaSAndroid Build Coastguard Worker skgpu::UniqueKey key;
1034*c8dee2aaSAndroid Build Coastguard Worker make_unique_key<0>(&key, 0);
1035*c8dee2aaSAndroid Build Coastguard Worker
1036*c8dee2aaSAndroid Build Coastguard Worker // Create two resources that we will attempt to register with the same unique key.
1037*c8dee2aaSAndroid Build Coastguard Worker TestResource* a = new TestResource(gpu, /*label=*/{}, skgpu::Budgeted::kYes, 11);
1038*c8dee2aaSAndroid Build Coastguard Worker
1039*c8dee2aaSAndroid Build Coastguard Worker // Set key on resource a.
1040*c8dee2aaSAndroid Build Coastguard Worker a->resourcePriv().setUniqueKey(key);
1041*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, a == cache->findAndRefUniqueResource(key));
1042*c8dee2aaSAndroid Build Coastguard Worker a->unref();
1043*c8dee2aaSAndroid Build Coastguard Worker
1044*c8dee2aaSAndroid Build Coastguard Worker // Make sure that redundantly setting a's key works.
1045*c8dee2aaSAndroid Build Coastguard Worker a->resourcePriv().setUniqueKey(key);
1046*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, a == cache->findAndRefUniqueResource(key));
1047*c8dee2aaSAndroid Build Coastguard Worker a->unref();
1048*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
1049*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, a->gpuMemorySize() == cache->getResourceBytes());
1050*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
1051*c8dee2aaSAndroid Build Coastguard Worker
1052*c8dee2aaSAndroid Build Coastguard Worker // Create resource b and set the same key. It should replace a's unique key cache entry.
1053*c8dee2aaSAndroid Build Coastguard Worker TestResource* b = new TestResource(gpu, /*label=*/{}, skgpu::Budgeted::kYes, 12);
1054*c8dee2aaSAndroid Build Coastguard Worker b->resourcePriv().setUniqueKey(key);
1055*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, b == cache->findAndRefUniqueResource(key));
1056*c8dee2aaSAndroid Build Coastguard Worker b->unref();
1057*c8dee2aaSAndroid Build Coastguard Worker
1058*c8dee2aaSAndroid Build Coastguard Worker // Still have two resources because a is still reffed.
1059*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
1060*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() == cache->getResourceBytes());
1061*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
1062*c8dee2aaSAndroid Build Coastguard Worker
1063*c8dee2aaSAndroid Build Coastguard Worker a->unref();
1064*c8dee2aaSAndroid Build Coastguard Worker // Now a should be gone.
1065*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
1066*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, b->gpuMemorySize() == cache->getResourceBytes());
1067*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
1068*c8dee2aaSAndroid Build Coastguard Worker
1069*c8dee2aaSAndroid Build Coastguard Worker // Now replace b with c, but make sure c can start with one unique key and change it to b's key.
1070*c8dee2aaSAndroid Build Coastguard Worker // Also make b be unreffed when replacement occurs.
1071*c8dee2aaSAndroid Build Coastguard Worker b->unref();
1072*c8dee2aaSAndroid Build Coastguard Worker TestResource* c = new TestResource(gpu, /*label=*/{}, skgpu::Budgeted::kYes, 13);
1073*c8dee2aaSAndroid Build Coastguard Worker skgpu::UniqueKey differentKey;
1074*c8dee2aaSAndroid Build Coastguard Worker make_unique_key<0>(&differentKey, 1);
1075*c8dee2aaSAndroid Build Coastguard Worker c->resourcePriv().setUniqueKey(differentKey);
1076*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
1077*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, b->gpuMemorySize() + c->gpuMemorySize() == cache->getResourceBytes());
1078*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
1079*c8dee2aaSAndroid Build Coastguard Worker // c replaces b and b should be immediately purged.
1080*c8dee2aaSAndroid Build Coastguard Worker c->resourcePriv().setUniqueKey(key);
1081*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
1082*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, c->gpuMemorySize() == cache->getResourceBytes());
1083*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
1084*c8dee2aaSAndroid Build Coastguard Worker
1085*c8dee2aaSAndroid Build Coastguard Worker // c shouldn't be purged because it is ref'ed.
1086*c8dee2aaSAndroid Build Coastguard Worker cache->purgeUnlockedResources(GrPurgeResourceOptions::kAllResources);
1087*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
1088*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, c->gpuMemorySize() == cache->getResourceBytes());
1089*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
1090*c8dee2aaSAndroid Build Coastguard Worker
1091*c8dee2aaSAndroid Build Coastguard Worker // Drop the ref on c, it should be kept alive because it has a unique key.
1092*c8dee2aaSAndroid Build Coastguard Worker c->unref();
1093*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
1094*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, c->gpuMemorySize() == cache->getResourceBytes());
1095*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
1096*c8dee2aaSAndroid Build Coastguard Worker
1097*c8dee2aaSAndroid Build Coastguard Worker // Verify that we can find c, then remove its unique key. It should get purged immediately.
1098*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, c == cache->findAndRefUniqueResource(key));
1099*c8dee2aaSAndroid Build Coastguard Worker c->resourcePriv().removeUniqueKey();
1100*c8dee2aaSAndroid Build Coastguard Worker c->unref();
1101*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
1102*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
1103*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
1104*c8dee2aaSAndroid Build Coastguard Worker
1105*c8dee2aaSAndroid Build Coastguard Worker {
1106*c8dee2aaSAndroid Build Coastguard Worker skgpu::UniqueKey key2;
1107*c8dee2aaSAndroid Build Coastguard Worker make_unique_key<0>(&key2, 0);
1108*c8dee2aaSAndroid Build Coastguard Worker sk_sp<TestResource> d(new TestResource(gpu, /*label=*/{}));
1109*c8dee2aaSAndroid Build Coastguard Worker int foo = 4132;
1110*c8dee2aaSAndroid Build Coastguard Worker key2.setCustomData(SkData::MakeWithCopy(&foo, sizeof(foo)));
1111*c8dee2aaSAndroid Build Coastguard Worker d->resourcePriv().setUniqueKey(key2);
1112*c8dee2aaSAndroid Build Coastguard Worker }
1113*c8dee2aaSAndroid Build Coastguard Worker
1114*c8dee2aaSAndroid Build Coastguard Worker skgpu::UniqueKey key3;
1115*c8dee2aaSAndroid Build Coastguard Worker make_unique_key<0>(&key3, 0);
1116*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrGpuResource> d2(cache->findAndRefUniqueResource(key3));
1117*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, *(const int*) d2->getUniqueKey().getCustomData()->data() == 4132);
1118*c8dee2aaSAndroid Build Coastguard Worker }
1119*c8dee2aaSAndroid Build Coastguard Worker
test_purge_invalidated(skiatest::Reporter * reporter)1120*c8dee2aaSAndroid Build Coastguard Worker static void test_purge_invalidated(skiatest::Reporter* reporter) {
1121*c8dee2aaSAndroid Build Coastguard Worker Mock mock(30000);
1122*c8dee2aaSAndroid Build Coastguard Worker auto dContext = mock.dContext();
1123*c8dee2aaSAndroid Build Coastguard Worker GrResourceCache* cache = mock.cache();
1124*c8dee2aaSAndroid Build Coastguard Worker GrGpu* gpu = mock.gpu();
1125*c8dee2aaSAndroid Build Coastguard Worker
1126*c8dee2aaSAndroid Build Coastguard Worker skgpu::UniqueKey key1, key2, key3;
1127*c8dee2aaSAndroid Build Coastguard Worker make_unique_key<0>(&key1, 1);
1128*c8dee2aaSAndroid Build Coastguard Worker make_unique_key<0>(&key2, 2);
1129*c8dee2aaSAndroid Build Coastguard Worker make_unique_key<0>(&key3, 3);
1130*c8dee2aaSAndroid Build Coastguard Worker
1131*c8dee2aaSAndroid Build Coastguard Worker // Add three resources to the cache. Only c is usable as scratch.
1132*c8dee2aaSAndroid Build Coastguard Worker TestResource* a = new TestResource(gpu, /*label=*/{});
1133*c8dee2aaSAndroid Build Coastguard Worker TestResource* b = new TestResource(gpu, /*label=*/{});
1134*c8dee2aaSAndroid Build Coastguard Worker TestResource* c = TestResource::CreateScratch(
1135*c8dee2aaSAndroid Build Coastguard Worker gpu, skgpu::Budgeted::kYes, TestResource::kA_SimulatedProperty);
1136*c8dee2aaSAndroid Build Coastguard Worker a->resourcePriv().setUniqueKey(key1);
1137*c8dee2aaSAndroid Build Coastguard Worker b->resourcePriv().setUniqueKey(key2);
1138*c8dee2aaSAndroid Build Coastguard Worker c->resourcePriv().setUniqueKey(key3);
1139*c8dee2aaSAndroid Build Coastguard Worker a->unref();
1140*c8dee2aaSAndroid Build Coastguard Worker // hold b until *after* the message is sent.
1141*c8dee2aaSAndroid Build Coastguard Worker c->unref();
1142*c8dee2aaSAndroid Build Coastguard Worker
1143*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, cache->hasUniqueKey(key1));
1144*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, cache->hasUniqueKey(key2));
1145*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, cache->hasUniqueKey(key3));
1146*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 3 == TestResource::NumAlive());
1147*c8dee2aaSAndroid Build Coastguard Worker
1148*c8dee2aaSAndroid Build Coastguard Worker typedef skgpu::UniqueKeyInvalidatedMessage Msg;
1149*c8dee2aaSAndroid Build Coastguard Worker typedef SkMessageBus<Msg, uint32_t> Bus;
1150*c8dee2aaSAndroid Build Coastguard Worker
1151*c8dee2aaSAndroid Build Coastguard Worker // Invalidate two of the three, they should be purged and no longer accessible via their keys.
1152*c8dee2aaSAndroid Build Coastguard Worker Bus::Post(Msg(key1, dContext->priv().contextID()));
1153*c8dee2aaSAndroid Build Coastguard Worker Bus::Post(Msg(key2, dContext->priv().contextID()));
1154*c8dee2aaSAndroid Build Coastguard Worker cache->purgeAsNeeded();
1155*c8dee2aaSAndroid Build Coastguard Worker // a should be deleted now, but we still have a ref on b.
1156*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key1));
1157*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key2));
1158*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
1159*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, cache->hasUniqueKey(key3));
1160*c8dee2aaSAndroid Build Coastguard Worker
1161*c8dee2aaSAndroid Build Coastguard Worker // Invalidate the third.
1162*c8dee2aaSAndroid Build Coastguard Worker Bus::Post(Msg(key3, dContext->priv().contextID()));
1163*c8dee2aaSAndroid Build Coastguard Worker cache->purgeAsNeeded();
1164*c8dee2aaSAndroid Build Coastguard Worker // we still have a ref on b, c should be recycled as scratch.
1165*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
1166*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key3));
1167*c8dee2aaSAndroid Build Coastguard Worker
1168*c8dee2aaSAndroid Build Coastguard Worker // make b purgeable. It should be immediately deleted since it has no key.
1169*c8dee2aaSAndroid Build Coastguard Worker b->unref();
1170*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
1171*c8dee2aaSAndroid Build Coastguard Worker
1172*c8dee2aaSAndroid Build Coastguard Worker // Make sure we actually get to c via it's scratch key, before we say goodbye.
1173*c8dee2aaSAndroid Build Coastguard Worker skgpu::ScratchKey scratchKey;
1174*c8dee2aaSAndroid Build Coastguard Worker TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey);
1175*c8dee2aaSAndroid Build Coastguard Worker GrGpuResource* scratch = cache->findAndRefScratchResource(scratchKey);
1176*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, scratch == c);
1177*c8dee2aaSAndroid Build Coastguard Worker SkSafeUnref(scratch);
1178*c8dee2aaSAndroid Build Coastguard Worker
1179*c8dee2aaSAndroid Build Coastguard Worker // Get rid of c.
1180*c8dee2aaSAndroid Build Coastguard Worker cache->purgeUnlockedResources(GrPurgeResourceOptions::kAllResources);
1181*c8dee2aaSAndroid Build Coastguard Worker scratch = cache->findAndRefScratchResource(scratchKey);
1182*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
1183*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
1184*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
1185*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !scratch);
1186*c8dee2aaSAndroid Build Coastguard Worker SkSafeUnref(scratch);
1187*c8dee2aaSAndroid Build Coastguard Worker }
1188*c8dee2aaSAndroid Build Coastguard Worker
test_cache_chained_purge(skiatest::Reporter * reporter)1189*c8dee2aaSAndroid Build Coastguard Worker static void test_cache_chained_purge(skiatest::Reporter* reporter) {
1190*c8dee2aaSAndroid Build Coastguard Worker Mock mock(30000);
1191*c8dee2aaSAndroid Build Coastguard Worker GrResourceCache* cache = mock.cache();
1192*c8dee2aaSAndroid Build Coastguard Worker GrGpu* gpu = mock.gpu();
1193*c8dee2aaSAndroid Build Coastguard Worker
1194*c8dee2aaSAndroid Build Coastguard Worker skgpu::UniqueKey key1, key2;
1195*c8dee2aaSAndroid Build Coastguard Worker make_unique_key<0>(&key1, 1);
1196*c8dee2aaSAndroid Build Coastguard Worker make_unique_key<0>(&key2, 2);
1197*c8dee2aaSAndroid Build Coastguard Worker
1198*c8dee2aaSAndroid Build Coastguard Worker sk_sp<TestResource> a(new TestResource(gpu, /*label=*/{}));
1199*c8dee2aaSAndroid Build Coastguard Worker sk_sp<TestResource> b(new TestResource(gpu, /*label=*/{}));
1200*c8dee2aaSAndroid Build Coastguard Worker a->resourcePriv().setUniqueKey(key1);
1201*c8dee2aaSAndroid Build Coastguard Worker b->resourcePriv().setUniqueKey(key2);
1202*c8dee2aaSAndroid Build Coastguard Worker
1203*c8dee2aaSAndroid Build Coastguard Worker // Make a cycle
1204*c8dee2aaSAndroid Build Coastguard Worker a->setUnrefWhenDestroyed(b);
1205*c8dee2aaSAndroid Build Coastguard Worker b->setUnrefWhenDestroyed(a);
1206*c8dee2aaSAndroid Build Coastguard Worker
1207*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
1208*c8dee2aaSAndroid Build Coastguard Worker
1209*c8dee2aaSAndroid Build Coastguard Worker TestResource* unownedA = a.release();
1210*c8dee2aaSAndroid Build Coastguard Worker unownedA->unref();
1211*c8dee2aaSAndroid Build Coastguard Worker b.reset();
1212*c8dee2aaSAndroid Build Coastguard Worker
1213*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
1214*c8dee2aaSAndroid Build Coastguard Worker
1215*c8dee2aaSAndroid Build Coastguard Worker cache->purgeUnlockedResources(GrPurgeResourceOptions::kAllResources);
1216*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
1217*c8dee2aaSAndroid Build Coastguard Worker
1218*c8dee2aaSAndroid Build Coastguard Worker // Break the cycle
1219*c8dee2aaSAndroid Build Coastguard Worker unownedA->setUnrefWhenDestroyed(nullptr);
1220*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
1221*c8dee2aaSAndroid Build Coastguard Worker
1222*c8dee2aaSAndroid Build Coastguard Worker cache->purgeUnlockedResources(GrPurgeResourceOptions::kAllResources);
1223*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
1224*c8dee2aaSAndroid Build Coastguard Worker }
1225*c8dee2aaSAndroid Build Coastguard Worker
test_timestamp_wrap(skiatest::Reporter * reporter)1226*c8dee2aaSAndroid Build Coastguard Worker static void test_timestamp_wrap(skiatest::Reporter* reporter) {
1227*c8dee2aaSAndroid Build Coastguard Worker static const int kCount = 50;
1228*c8dee2aaSAndroid Build Coastguard Worker static const int kLockedFreq = 8;
1229*c8dee2aaSAndroid Build Coastguard Worker static const int kBudgetSize = 0; // always over budget
1230*c8dee2aaSAndroid Build Coastguard Worker
1231*c8dee2aaSAndroid Build Coastguard Worker SkRandom random;
1232*c8dee2aaSAndroid Build Coastguard Worker
1233*c8dee2aaSAndroid Build Coastguard Worker // Run the test 2*kCount times;
1234*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 2 * kCount; ++i ) {
1235*c8dee2aaSAndroid Build Coastguard Worker Mock mock(kBudgetSize);
1236*c8dee2aaSAndroid Build Coastguard Worker GrResourceCache* cache = mock.cache();
1237*c8dee2aaSAndroid Build Coastguard Worker GrGpu* gpu = mock.gpu();
1238*c8dee2aaSAndroid Build Coastguard Worker
1239*c8dee2aaSAndroid Build Coastguard Worker // Pick a random number of resources to add before the timestamp will wrap.
1240*c8dee2aaSAndroid Build Coastguard Worker cache->changeTimestamp(UINT32_MAX - random.nextULessThan(kCount + 1));
1241*c8dee2aaSAndroid Build Coastguard Worker
1242*c8dee2aaSAndroid Build Coastguard Worker static const int kNumToPurge = kCount;
1243*c8dee2aaSAndroid Build Coastguard Worker
1244*c8dee2aaSAndroid Build Coastguard Worker SkTDArray<int> shouldPurgeIdxs;
1245*c8dee2aaSAndroid Build Coastguard Worker int purgeableCnt = 0;
1246*c8dee2aaSAndroid Build Coastguard Worker SkTDArray<GrGpuResource*> resourcesToUnref;
1247*c8dee2aaSAndroid Build Coastguard Worker
1248*c8dee2aaSAndroid Build Coastguard Worker // Add kCount resources, holding onto resources at random so we have a mix of purgeable and
1249*c8dee2aaSAndroid Build Coastguard Worker // unpurgeable resources.
1250*c8dee2aaSAndroid Build Coastguard Worker for (int j = 0; j < kCount; ++j) {
1251*c8dee2aaSAndroid Build Coastguard Worker skgpu::UniqueKey key;
1252*c8dee2aaSAndroid Build Coastguard Worker make_unique_key<0>(&key, j);
1253*c8dee2aaSAndroid Build Coastguard Worker
1254*c8dee2aaSAndroid Build Coastguard Worker TestResource* r = new TestResource(gpu, /*label=*/{});
1255*c8dee2aaSAndroid Build Coastguard Worker r->resourcePriv().setUniqueKey(key);
1256*c8dee2aaSAndroid Build Coastguard Worker if (random.nextU() % kLockedFreq) {
1257*c8dee2aaSAndroid Build Coastguard Worker // Make this is purgeable.
1258*c8dee2aaSAndroid Build Coastguard Worker r->unref();
1259*c8dee2aaSAndroid Build Coastguard Worker ++purgeableCnt;
1260*c8dee2aaSAndroid Build Coastguard Worker if (purgeableCnt <= kNumToPurge) {
1261*c8dee2aaSAndroid Build Coastguard Worker *shouldPurgeIdxs.append() = j;
1262*c8dee2aaSAndroid Build Coastguard Worker }
1263*c8dee2aaSAndroid Build Coastguard Worker } else {
1264*c8dee2aaSAndroid Build Coastguard Worker *resourcesToUnref.append() = r;
1265*c8dee2aaSAndroid Build Coastguard Worker }
1266*c8dee2aaSAndroid Build Coastguard Worker }
1267*c8dee2aaSAndroid Build Coastguard Worker
1268*c8dee2aaSAndroid Build Coastguard Worker // Verify that the correct resources were purged.
1269*c8dee2aaSAndroid Build Coastguard Worker int currShouldPurgeIdx = 0;
1270*c8dee2aaSAndroid Build Coastguard Worker for (int j = 0; j < kCount; ++j) {
1271*c8dee2aaSAndroid Build Coastguard Worker skgpu::UniqueKey key;
1272*c8dee2aaSAndroid Build Coastguard Worker make_unique_key<0>(&key, j);
1273*c8dee2aaSAndroid Build Coastguard Worker GrGpuResource* res = cache->findAndRefUniqueResource(key);
1274*c8dee2aaSAndroid Build Coastguard Worker if (currShouldPurgeIdx < shouldPurgeIdxs.size() &&
1275*c8dee2aaSAndroid Build Coastguard Worker shouldPurgeIdxs[currShouldPurgeIdx] == j) {
1276*c8dee2aaSAndroid Build Coastguard Worker ++currShouldPurgeIdx;
1277*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, nullptr == res);
1278*c8dee2aaSAndroid Build Coastguard Worker } else {
1279*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, nullptr != res);
1280*c8dee2aaSAndroid Build Coastguard Worker }
1281*c8dee2aaSAndroid Build Coastguard Worker SkSafeUnref(res);
1282*c8dee2aaSAndroid Build Coastguard Worker }
1283*c8dee2aaSAndroid Build Coastguard Worker
1284*c8dee2aaSAndroid Build Coastguard Worker for (int j = 0; j < resourcesToUnref.size(); ++j) {
1285*c8dee2aaSAndroid Build Coastguard Worker resourcesToUnref[j]->unref();
1286*c8dee2aaSAndroid Build Coastguard Worker }
1287*c8dee2aaSAndroid Build Coastguard Worker }
1288*c8dee2aaSAndroid Build Coastguard Worker }
1289*c8dee2aaSAndroid Build Coastguard Worker
test_time_purge(skiatest::Reporter * reporter)1290*c8dee2aaSAndroid Build Coastguard Worker static void test_time_purge(skiatest::Reporter* reporter) {
1291*c8dee2aaSAndroid Build Coastguard Worker Mock mock(1000000);
1292*c8dee2aaSAndroid Build Coastguard Worker auto dContext = mock.dContext();
1293*c8dee2aaSAndroid Build Coastguard Worker GrResourceCache* cache = mock.cache();
1294*c8dee2aaSAndroid Build Coastguard Worker GrGpu* gpu = mock.gpu();
1295*c8dee2aaSAndroid Build Coastguard Worker
1296*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kCnts[] = {1, 10, 1024};
1297*c8dee2aaSAndroid Build Coastguard Worker auto nowish = []() {
1298*c8dee2aaSAndroid Build Coastguard Worker // We sleep so that we ensure we get a value that is greater than the last call to
1299*c8dee2aaSAndroid Build Coastguard Worker // GrStdSteadyClock::now().
1300*c8dee2aaSAndroid Build Coastguard Worker std::this_thread::sleep_for(skgpu::StdSteadyClock::duration(5));
1301*c8dee2aaSAndroid Build Coastguard Worker auto result = skgpu::StdSteadyClock::now();
1302*c8dee2aaSAndroid Build Coastguard Worker // Also sleep afterwards so we don't get this value again.
1303*c8dee2aaSAndroid Build Coastguard Worker std::this_thread::sleep_for(skgpu::StdSteadyClock::duration(5));
1304*c8dee2aaSAndroid Build Coastguard Worker return result;
1305*c8dee2aaSAndroid Build Coastguard Worker };
1306*c8dee2aaSAndroid Build Coastguard Worker
1307*c8dee2aaSAndroid Build Coastguard Worker for (int cnt : kCnts) {
1308*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<skgpu::StdSteadyClock::time_point[]> timeStamps(
1309*c8dee2aaSAndroid Build Coastguard Worker new skgpu::StdSteadyClock::time_point[cnt]);
1310*c8dee2aaSAndroid Build Coastguard Worker {
1311*c8dee2aaSAndroid Build Coastguard Worker // Insert resources and get time points between each addition.
1312*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < cnt; ++i) {
1313*c8dee2aaSAndroid Build Coastguard Worker TestResource* r = new TestResource(gpu, /*label=*/{});
1314*c8dee2aaSAndroid Build Coastguard Worker skgpu::UniqueKey k;
1315*c8dee2aaSAndroid Build Coastguard Worker make_unique_key<1>(&k, i);
1316*c8dee2aaSAndroid Build Coastguard Worker r->resourcePriv().setUniqueKey(k);
1317*c8dee2aaSAndroid Build Coastguard Worker r->unref();
1318*c8dee2aaSAndroid Build Coastguard Worker timeStamps.get()[i] = nowish();
1319*c8dee2aaSAndroid Build Coastguard Worker }
1320*c8dee2aaSAndroid Build Coastguard Worker
1321*c8dee2aaSAndroid Build Coastguard Worker // Purge based on the time points between resource additions. Each purge should remove
1322*c8dee2aaSAndroid Build Coastguard Worker // the oldest resource.
1323*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < cnt; ++i) {
1324*c8dee2aaSAndroid Build Coastguard Worker cache->purgeResourcesNotUsedSince(timeStamps[i],
1325*c8dee2aaSAndroid Build Coastguard Worker GrPurgeResourceOptions::kAllResources);
1326*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, cnt - i - 1 == cache->getResourceCount());
1327*c8dee2aaSAndroid Build Coastguard Worker for (int j = 0; j < i; ++j) {
1328*c8dee2aaSAndroid Build Coastguard Worker skgpu::UniqueKey k;
1329*c8dee2aaSAndroid Build Coastguard Worker make_unique_key<1>(&k, j);
1330*c8dee2aaSAndroid Build Coastguard Worker GrGpuResource* r = cache->findAndRefUniqueResource(k);
1331*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !SkToBool(r));
1332*c8dee2aaSAndroid Build Coastguard Worker SkSafeUnref(r);
1333*c8dee2aaSAndroid Build Coastguard Worker }
1334*c8dee2aaSAndroid Build Coastguard Worker }
1335*c8dee2aaSAndroid Build Coastguard Worker
1336*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
1337*c8dee2aaSAndroid Build Coastguard Worker cache->purgeUnlockedResources(GrPurgeResourceOptions::kAllResources);
1338*c8dee2aaSAndroid Build Coastguard Worker }
1339*c8dee2aaSAndroid Build Coastguard Worker
1340*c8dee2aaSAndroid Build Coastguard Worker // Do a similar test but where we leave refs on some resources to prevent them from being
1341*c8dee2aaSAndroid Build Coastguard Worker // purged.
1342*c8dee2aaSAndroid Build Coastguard Worker {
1343*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<GrGpuResource* []> refedResources(new GrGpuResource*[cnt / 2]);
1344*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < cnt; ++i) {
1345*c8dee2aaSAndroid Build Coastguard Worker TestResource* r = new TestResource(gpu, /*label=*/{});
1346*c8dee2aaSAndroid Build Coastguard Worker skgpu::UniqueKey k;
1347*c8dee2aaSAndroid Build Coastguard Worker make_unique_key<1>(&k, i);
1348*c8dee2aaSAndroid Build Coastguard Worker r->resourcePriv().setUniqueKey(k);
1349*c8dee2aaSAndroid Build Coastguard Worker // Leave a ref on every other resource, beginning with the first.
1350*c8dee2aaSAndroid Build Coastguard Worker if (SkToBool(i & 0x1)) {
1351*c8dee2aaSAndroid Build Coastguard Worker refedResources.get()[i / 2] = r;
1352*c8dee2aaSAndroid Build Coastguard Worker } else {
1353*c8dee2aaSAndroid Build Coastguard Worker r->unref();
1354*c8dee2aaSAndroid Build Coastguard Worker }
1355*c8dee2aaSAndroid Build Coastguard Worker timeStamps.get()[i] = nowish();
1356*c8dee2aaSAndroid Build Coastguard Worker }
1357*c8dee2aaSAndroid Build Coastguard Worker
1358*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < cnt; ++i) {
1359*c8dee2aaSAndroid Build Coastguard Worker // Should get a resource purged every other frame.
1360*c8dee2aaSAndroid Build Coastguard Worker cache->purgeResourcesNotUsedSince(timeStamps[i],
1361*c8dee2aaSAndroid Build Coastguard Worker GrPurgeResourceOptions::kAllResources);
1362*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, cnt - i / 2 - 1 == cache->getResourceCount());
1363*c8dee2aaSAndroid Build Coastguard Worker }
1364*c8dee2aaSAndroid Build Coastguard Worker
1365*c8dee2aaSAndroid Build Coastguard Worker // Unref all the resources that we kept refs on in the first loop.
1366*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < (cnt / 2); ++i) {
1367*c8dee2aaSAndroid Build Coastguard Worker refedResources.get()[i]->unref();
1368*c8dee2aaSAndroid Build Coastguard Worker cache->purgeResourcesNotUsedSince(nowish(), GrPurgeResourceOptions::kAllResources);
1369*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, cnt / 2 - i - 1 == cache->getResourceCount());
1370*c8dee2aaSAndroid Build Coastguard Worker }
1371*c8dee2aaSAndroid Build Coastguard Worker
1372*c8dee2aaSAndroid Build Coastguard Worker cache->purgeUnlockedResources(GrPurgeResourceOptions::kAllResources);
1373*c8dee2aaSAndroid Build Coastguard Worker }
1374*c8dee2aaSAndroid Build Coastguard Worker
1375*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
1376*c8dee2aaSAndroid Build Coastguard Worker
1377*c8dee2aaSAndroid Build Coastguard Worker // Do a similar test where we alternate adding scratch and uniquely keyed resources, but
1378*c8dee2aaSAndroid Build Coastguard Worker // then purge old scratch resources.
1379*c8dee2aaSAndroid Build Coastguard Worker {
1380*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < cnt; ++i) {
1381*c8dee2aaSAndroid Build Coastguard Worker const bool isScratch = (i % 2 == 0);
1382*c8dee2aaSAndroid Build Coastguard Worker const skgpu::Budgeted budgeted = skgpu::Budgeted::kYes;
1383*c8dee2aaSAndroid Build Coastguard Worker const TestResource::SimulatedProperty property = TestResource::kA_SimulatedProperty;
1384*c8dee2aaSAndroid Build Coastguard Worker TestResource* r = isScratch
1385*c8dee2aaSAndroid Build Coastguard Worker ? TestResource::CreateScratch(gpu, budgeted, property)
1386*c8dee2aaSAndroid Build Coastguard Worker : new TestResource(gpu, /*label=*/{}, budgeted, property);
1387*c8dee2aaSAndroid Build Coastguard Worker if (!isScratch) {
1388*c8dee2aaSAndroid Build Coastguard Worker skgpu::UniqueKey k;
1389*c8dee2aaSAndroid Build Coastguard Worker make_unique_key<1>(&k, i);
1390*c8dee2aaSAndroid Build Coastguard Worker r->resourcePriv().setUniqueKey(k);
1391*c8dee2aaSAndroid Build Coastguard Worker }
1392*c8dee2aaSAndroid Build Coastguard Worker r->unref();
1393*c8dee2aaSAndroid Build Coastguard Worker timeStamps.get()[i] = nowish();
1394*c8dee2aaSAndroid Build Coastguard Worker }
1395*c8dee2aaSAndroid Build Coastguard Worker
1396*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < cnt; ++i) {
1397*c8dee2aaSAndroid Build Coastguard Worker // Should get a resource purged every other frame, since the uniquely keyed
1398*c8dee2aaSAndroid Build Coastguard Worker // resources will not be considered.
1399*c8dee2aaSAndroid Build Coastguard Worker cache->purgeResourcesNotUsedSince(timeStamps[i],
1400*c8dee2aaSAndroid Build Coastguard Worker GrPurgeResourceOptions::kScratchResourcesOnly);
1401*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, cnt - i / 2 - 1 == cache->getResourceCount());
1402*c8dee2aaSAndroid Build Coastguard Worker }
1403*c8dee2aaSAndroid Build Coastguard Worker // Unref remaining resources
1404*c8dee2aaSAndroid Build Coastguard Worker cache->purgeResourcesNotUsedSince(nowish(), GrPurgeResourceOptions::kAllResources);
1405*c8dee2aaSAndroid Build Coastguard Worker }
1406*c8dee2aaSAndroid Build Coastguard Worker
1407*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
1408*c8dee2aaSAndroid Build Coastguard Worker
1409*c8dee2aaSAndroid Build Coastguard Worker // Verify that calling flush() on a context with nothing to do will not trigger resource
1410*c8dee2aaSAndroid Build Coastguard Worker // eviction
1411*c8dee2aaSAndroid Build Coastguard Worker dContext->flushAndSubmit();
1412*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 10; ++i) {
1413*c8dee2aaSAndroid Build Coastguard Worker TestResource* r = new TestResource(gpu, /*label=*/{});
1414*c8dee2aaSAndroid Build Coastguard Worker skgpu::UniqueKey k;
1415*c8dee2aaSAndroid Build Coastguard Worker make_unique_key<1>(&k, i);
1416*c8dee2aaSAndroid Build Coastguard Worker r->resourcePriv().setUniqueKey(k);
1417*c8dee2aaSAndroid Build Coastguard Worker r->unref();
1418*c8dee2aaSAndroid Build Coastguard Worker }
1419*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 10 == cache->getResourceCount());
1420*c8dee2aaSAndroid Build Coastguard Worker dContext->flushAndSubmit();
1421*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 10 == cache->getResourceCount());
1422*c8dee2aaSAndroid Build Coastguard Worker cache->purgeResourcesNotUsedSince(nowish(), GrPurgeResourceOptions::kAllResources);
1423*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
1424*c8dee2aaSAndroid Build Coastguard Worker }
1425*c8dee2aaSAndroid Build Coastguard Worker }
1426*c8dee2aaSAndroid Build Coastguard Worker
test_partial_purge(skiatest::Reporter * reporter)1427*c8dee2aaSAndroid Build Coastguard Worker static void test_partial_purge(skiatest::Reporter* reporter) {
1428*c8dee2aaSAndroid Build Coastguard Worker Mock mock(100);
1429*c8dee2aaSAndroid Build Coastguard Worker auto dContext = mock.dContext();
1430*c8dee2aaSAndroid Build Coastguard Worker GrResourceCache* cache = mock.cache();
1431*c8dee2aaSAndroid Build Coastguard Worker GrGpu* gpu = mock.gpu();
1432*c8dee2aaSAndroid Build Coastguard Worker
1433*c8dee2aaSAndroid Build Coastguard Worker enum TestsCase {
1434*c8dee2aaSAndroid Build Coastguard Worker kOnlyScratch_TestCase = 0,
1435*c8dee2aaSAndroid Build Coastguard Worker kPartialScratch_TestCase = 1,
1436*c8dee2aaSAndroid Build Coastguard Worker kAllScratch_TestCase = 2,
1437*c8dee2aaSAndroid Build Coastguard Worker kPartial_TestCase = 3,
1438*c8dee2aaSAndroid Build Coastguard Worker kAll_TestCase = 4,
1439*c8dee2aaSAndroid Build Coastguard Worker kNone_TestCase = 5,
1440*c8dee2aaSAndroid Build Coastguard Worker kEndTests_TestCase = kNone_TestCase + 1
1441*c8dee2aaSAndroid Build Coastguard Worker };
1442*c8dee2aaSAndroid Build Coastguard Worker
1443*c8dee2aaSAndroid Build Coastguard Worker for (int testCase = 0; testCase < kEndTests_TestCase; testCase++) {
1444*c8dee2aaSAndroid Build Coastguard Worker
1445*c8dee2aaSAndroid Build Coastguard Worker skgpu::UniqueKey key1, key2, key3;
1446*c8dee2aaSAndroid Build Coastguard Worker make_unique_key<0>(&key1, 1);
1447*c8dee2aaSAndroid Build Coastguard Worker make_unique_key<0>(&key2, 2);
1448*c8dee2aaSAndroid Build Coastguard Worker make_unique_key<0>(&key3, 3);
1449*c8dee2aaSAndroid Build Coastguard Worker
1450*c8dee2aaSAndroid Build Coastguard Worker // Add three unique resources to the cache.
1451*c8dee2aaSAndroid Build Coastguard Worker TestResource* unique1 = new TestResource(gpu, /*label=*/{}, skgpu::Budgeted::kYes, 10);
1452*c8dee2aaSAndroid Build Coastguard Worker TestResource* unique2 = new TestResource(gpu, /*label=*/{}, skgpu::Budgeted::kYes, 11);
1453*c8dee2aaSAndroid Build Coastguard Worker TestResource* unique3 = new TestResource(gpu, /*label=*/{}, skgpu::Budgeted::kYes, 12);
1454*c8dee2aaSAndroid Build Coastguard Worker
1455*c8dee2aaSAndroid Build Coastguard Worker unique1->resourcePriv().setUniqueKey(key1);
1456*c8dee2aaSAndroid Build Coastguard Worker unique2->resourcePriv().setUniqueKey(key2);
1457*c8dee2aaSAndroid Build Coastguard Worker unique3->resourcePriv().setUniqueKey(key3);
1458*c8dee2aaSAndroid Build Coastguard Worker
1459*c8dee2aaSAndroid Build Coastguard Worker // Add two scratch resources to the cache.
1460*c8dee2aaSAndroid Build Coastguard Worker TestResource* scratch1 = TestResource::CreateScratch(
1461*c8dee2aaSAndroid Build Coastguard Worker gpu, skgpu::Budgeted::kYes, TestResource::kA_SimulatedProperty, 13);
1462*c8dee2aaSAndroid Build Coastguard Worker TestResource* scratch2 = TestResource::CreateScratch(
1463*c8dee2aaSAndroid Build Coastguard Worker gpu, skgpu::Budgeted::kYes, TestResource::kB_SimulatedProperty, 14);
1464*c8dee2aaSAndroid Build Coastguard Worker
1465*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 5 == cache->getBudgetedResourceCount());
1466*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 60 == cache->getBudgetedResourceBytes());
1467*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
1468*c8dee2aaSAndroid Build Coastguard Worker
1469*c8dee2aaSAndroid Build Coastguard Worker // Add resources to the purgeable queue
1470*c8dee2aaSAndroid Build Coastguard Worker unique1->unref();
1471*c8dee2aaSAndroid Build Coastguard Worker scratch1->unref();
1472*c8dee2aaSAndroid Build Coastguard Worker unique2->unref();
1473*c8dee2aaSAndroid Build Coastguard Worker scratch2->unref();
1474*c8dee2aaSAndroid Build Coastguard Worker unique3->unref();
1475*c8dee2aaSAndroid Build Coastguard Worker
1476*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 5 == cache->getBudgetedResourceCount());
1477*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 60 == cache->getBudgetedResourceBytes());
1478*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 60 == cache->getPurgeableBytes());
1479*c8dee2aaSAndroid Build Coastguard Worker
1480*c8dee2aaSAndroid Build Coastguard Worker switch(testCase) {
1481*c8dee2aaSAndroid Build Coastguard Worker case kOnlyScratch_TestCase: {
1482*c8dee2aaSAndroid Build Coastguard Worker dContext->purgeUnlockedResources(14, true);
1483*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 3 == cache->getBudgetedResourceCount());
1484*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 33 == cache->getBudgetedResourceBytes());
1485*c8dee2aaSAndroid Build Coastguard Worker break;
1486*c8dee2aaSAndroid Build Coastguard Worker }
1487*c8dee2aaSAndroid Build Coastguard Worker case kPartialScratch_TestCase: {
1488*c8dee2aaSAndroid Build Coastguard Worker dContext->purgeUnlockedResources(3, true);
1489*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 4 == cache->getBudgetedResourceCount());
1490*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 47 == cache->getBudgetedResourceBytes());
1491*c8dee2aaSAndroid Build Coastguard Worker break;
1492*c8dee2aaSAndroid Build Coastguard Worker }
1493*c8dee2aaSAndroid Build Coastguard Worker case kAllScratch_TestCase: {
1494*c8dee2aaSAndroid Build Coastguard Worker dContext->purgeUnlockedResources(50, true);
1495*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
1496*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
1497*c8dee2aaSAndroid Build Coastguard Worker break;
1498*c8dee2aaSAndroid Build Coastguard Worker }
1499*c8dee2aaSAndroid Build Coastguard Worker case kPartial_TestCase: {
1500*c8dee2aaSAndroid Build Coastguard Worker dContext->purgeUnlockedResources(13, false);
1501*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 3 == cache->getBudgetedResourceCount());
1502*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 37 == cache->getBudgetedResourceBytes());
1503*c8dee2aaSAndroid Build Coastguard Worker break;
1504*c8dee2aaSAndroid Build Coastguard Worker }
1505*c8dee2aaSAndroid Build Coastguard Worker case kAll_TestCase: {
1506*c8dee2aaSAndroid Build Coastguard Worker dContext->purgeUnlockedResources(50, false);
1507*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
1508*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
1509*c8dee2aaSAndroid Build Coastguard Worker break;
1510*c8dee2aaSAndroid Build Coastguard Worker }
1511*c8dee2aaSAndroid Build Coastguard Worker case kNone_TestCase: {
1512*c8dee2aaSAndroid Build Coastguard Worker dContext->purgeUnlockedResources(0, true);
1513*c8dee2aaSAndroid Build Coastguard Worker dContext->purgeUnlockedResources(0, false);
1514*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 5 == cache->getBudgetedResourceCount());
1515*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 60 == cache->getBudgetedResourceBytes());
1516*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 60 == cache->getPurgeableBytes());
1517*c8dee2aaSAndroid Build Coastguard Worker break;
1518*c8dee2aaSAndroid Build Coastguard Worker }
1519*c8dee2aaSAndroid Build Coastguard Worker }
1520*c8dee2aaSAndroid Build Coastguard Worker
1521*c8dee2aaSAndroid Build Coastguard Worker // ensure all are purged before the next
1522*c8dee2aaSAndroid Build Coastguard Worker dContext->priv().getResourceCache()->purgeUnlockedResources(
1523*c8dee2aaSAndroid Build Coastguard Worker GrPurgeResourceOptions::kAllResources);
1524*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
1525*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
1526*c8dee2aaSAndroid Build Coastguard Worker
1527*c8dee2aaSAndroid Build Coastguard Worker }
1528*c8dee2aaSAndroid Build Coastguard Worker }
1529*c8dee2aaSAndroid Build Coastguard Worker
test_custom_data(skiatest::Reporter * reporter)1530*c8dee2aaSAndroid Build Coastguard Worker static void test_custom_data(skiatest::Reporter* reporter) {
1531*c8dee2aaSAndroid Build Coastguard Worker skgpu::UniqueKey key1, key2;
1532*c8dee2aaSAndroid Build Coastguard Worker make_unique_key<0>(&key1, 1);
1533*c8dee2aaSAndroid Build Coastguard Worker make_unique_key<0>(&key2, 2);
1534*c8dee2aaSAndroid Build Coastguard Worker int foo = 4132;
1535*c8dee2aaSAndroid Build Coastguard Worker key1.setCustomData(SkData::MakeWithCopy(&foo, sizeof(foo)));
1536*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, *(const int*) key1.getCustomData()->data() == 4132);
1537*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, key2.getCustomData() == nullptr);
1538*c8dee2aaSAndroid Build Coastguard Worker
1539*c8dee2aaSAndroid Build Coastguard Worker // Test that copying a key also takes a ref on its custom data.
1540*c8dee2aaSAndroid Build Coastguard Worker skgpu::UniqueKey key3 = key1;
1541*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, *(const int*) key3.getCustomData()->data() == 4132);
1542*c8dee2aaSAndroid Build Coastguard Worker }
1543*c8dee2aaSAndroid Build Coastguard Worker
test_abandoned(skiatest::Reporter * reporter)1544*c8dee2aaSAndroid Build Coastguard Worker static void test_abandoned(skiatest::Reporter* reporter) {
1545*c8dee2aaSAndroid Build Coastguard Worker Mock mock(300);
1546*c8dee2aaSAndroid Build Coastguard Worker auto dContext = mock.dContext();
1547*c8dee2aaSAndroid Build Coastguard Worker GrGpu* gpu = mock.gpu();
1548*c8dee2aaSAndroid Build Coastguard Worker
1549*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrGpuResource> resource(new TestResource(gpu, /*label=*/{}));
1550*c8dee2aaSAndroid Build Coastguard Worker dContext->abandonContext();
1551*c8dee2aaSAndroid Build Coastguard Worker
1552*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resource->wasDestroyed());
1553*c8dee2aaSAndroid Build Coastguard Worker
1554*c8dee2aaSAndroid Build Coastguard Worker // Call all the public methods on resource in the abandoned state. They shouldn't crash.
1555*c8dee2aaSAndroid Build Coastguard Worker
1556*c8dee2aaSAndroid Build Coastguard Worker resource->uniqueID();
1557*c8dee2aaSAndroid Build Coastguard Worker resource->getUniqueKey();
1558*c8dee2aaSAndroid Build Coastguard Worker resource->wasDestroyed();
1559*c8dee2aaSAndroid Build Coastguard Worker resource->gpuMemorySize();
1560*c8dee2aaSAndroid Build Coastguard Worker resource->getContext();
1561*c8dee2aaSAndroid Build Coastguard Worker
1562*c8dee2aaSAndroid Build Coastguard Worker resource->resourcePriv().getScratchKey();
1563*c8dee2aaSAndroid Build Coastguard Worker resource->resourcePriv().budgetedType();
1564*c8dee2aaSAndroid Build Coastguard Worker resource->resourcePriv().makeBudgeted();
1565*c8dee2aaSAndroid Build Coastguard Worker resource->resourcePriv().makeUnbudgeted();
1566*c8dee2aaSAndroid Build Coastguard Worker resource->resourcePriv().removeScratchKey();
1567*c8dee2aaSAndroid Build Coastguard Worker skgpu::UniqueKey key;
1568*c8dee2aaSAndroid Build Coastguard Worker make_unique_key<0>(&key, 1);
1569*c8dee2aaSAndroid Build Coastguard Worker resource->resourcePriv().setUniqueKey(key);
1570*c8dee2aaSAndroid Build Coastguard Worker resource->resourcePriv().removeUniqueKey();
1571*c8dee2aaSAndroid Build Coastguard Worker }
1572*c8dee2aaSAndroid Build Coastguard Worker
test_tags(skiatest::Reporter * reporter)1573*c8dee2aaSAndroid Build Coastguard Worker static void test_tags(skiatest::Reporter* reporter) {
1574*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
1575*c8dee2aaSAndroid Build Coastguard Worker // We will insert 1 resource with tag "tag1", 2 with "tag2", and so on, up through kLastTagIdx.
1576*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kLastTagIdx = 10;
1577*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kNumResources = kLastTagIdx * (kLastTagIdx + 1) / 2;
1578*c8dee2aaSAndroid Build Coastguard Worker
1579*c8dee2aaSAndroid Build Coastguard Worker Mock mock(kNumResources * TestResource::kDefaultSize);
1580*c8dee2aaSAndroid Build Coastguard Worker GrResourceCache* cache = mock.cache();
1581*c8dee2aaSAndroid Build Coastguard Worker GrGpu* gpu = mock.gpu();
1582*c8dee2aaSAndroid Build Coastguard Worker
1583*c8dee2aaSAndroid Build Coastguard Worker // tag strings are expected to be long lived
1584*c8dee2aaSAndroid Build Coastguard Worker std::vector<SkString> tagStrings;
1585*c8dee2aaSAndroid Build Coastguard Worker
1586*c8dee2aaSAndroid Build Coastguard Worker SkString tagStr;
1587*c8dee2aaSAndroid Build Coastguard Worker int tagIdx = 0;
1588*c8dee2aaSAndroid Build Coastguard Worker int currTagCnt = 0;
1589*c8dee2aaSAndroid Build Coastguard Worker
1590*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < kNumResources; ++i, ++currTagCnt) {
1591*c8dee2aaSAndroid Build Coastguard Worker
1592*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrGpuResource> resource(new TestResource(gpu, /*label=*/{}));
1593*c8dee2aaSAndroid Build Coastguard Worker skgpu::UniqueKey key;
1594*c8dee2aaSAndroid Build Coastguard Worker if (currTagCnt == tagIdx) {
1595*c8dee2aaSAndroid Build Coastguard Worker tagIdx += 1;
1596*c8dee2aaSAndroid Build Coastguard Worker currTagCnt = 0;
1597*c8dee2aaSAndroid Build Coastguard Worker tagStr.printf("tag%d", tagIdx);
1598*c8dee2aaSAndroid Build Coastguard Worker tagStrings.emplace_back(tagStr);
1599*c8dee2aaSAndroid Build Coastguard Worker }
1600*c8dee2aaSAndroid Build Coastguard Worker make_unique_key<1>(&key, i, tagStrings.back().c_str());
1601*c8dee2aaSAndroid Build Coastguard Worker resource->resourcePriv().setUniqueKey(key);
1602*c8dee2aaSAndroid Build Coastguard Worker }
1603*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(kLastTagIdx == tagIdx);
1604*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(currTagCnt == kLastTagIdx);
1605*c8dee2aaSAndroid Build Coastguard Worker
1606*c8dee2aaSAndroid Build Coastguard Worker // Test i = 0 to exercise unused tag string.
1607*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i <= kLastTagIdx; ++i) {
1608*c8dee2aaSAndroid Build Coastguard Worker tagStr.printf("tag%d", i);
1609*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, cache->countUniqueKeysWithTag(tagStr.c_str()) == i);
1610*c8dee2aaSAndroid Build Coastguard Worker }
1611*c8dee2aaSAndroid Build Coastguard Worker #endif
1612*c8dee2aaSAndroid Build Coastguard Worker }
1613*c8dee2aaSAndroid Build Coastguard Worker
test_free_texture_messages(skiatest::Reporter * reporter)1614*c8dee2aaSAndroid Build Coastguard Worker static void test_free_texture_messages(skiatest::Reporter* reporter) {
1615*c8dee2aaSAndroid Build Coastguard Worker Mock mock(30000);
1616*c8dee2aaSAndroid Build Coastguard Worker auto dContext = mock.dContext();
1617*c8dee2aaSAndroid Build Coastguard Worker GrResourceCache* cache = mock.cache();
1618*c8dee2aaSAndroid Build Coastguard Worker GrGpu* gpu = mock.gpu();
1619*c8dee2aaSAndroid Build Coastguard Worker
1620*c8dee2aaSAndroid Build Coastguard Worker GrBackendTexture backends[3];
1621*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> wrapped[3];
1622*c8dee2aaSAndroid Build Coastguard Worker int freed[3] = { 0, 0, 0 };
1623*c8dee2aaSAndroid Build Coastguard Worker
1624*c8dee2aaSAndroid Build Coastguard Worker auto releaseProc = [](void* ctx) {
1625*c8dee2aaSAndroid Build Coastguard Worker int* index = (int*) ctx;
1626*c8dee2aaSAndroid Build Coastguard Worker *index = 1;
1627*c8dee2aaSAndroid Build Coastguard Worker };
1628*c8dee2aaSAndroid Build Coastguard Worker
1629*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 3; ++i) {
1630*c8dee2aaSAndroid Build Coastguard Worker backends[i] = dContext->createBackendTexture(16,
1631*c8dee2aaSAndroid Build Coastguard Worker 16,
1632*c8dee2aaSAndroid Build Coastguard Worker SkColorType::kRGBA_8888_SkColorType,
1633*c8dee2aaSAndroid Build Coastguard Worker skgpu::Mipmapped::kNo,
1634*c8dee2aaSAndroid Build Coastguard Worker GrRenderable::kNo);
1635*c8dee2aaSAndroid Build Coastguard Worker wrapped[i] = gpu->wrapBackendTexture(backends[i],
1636*c8dee2aaSAndroid Build Coastguard Worker GrWrapOwnership::kBorrow_GrWrapOwnership,
1637*c8dee2aaSAndroid Build Coastguard Worker (i < 2) ? GrWrapCacheable::kYes : GrWrapCacheable::kNo,
1638*c8dee2aaSAndroid Build Coastguard Worker GrIOType::kRead_GrIOType);
1639*c8dee2aaSAndroid Build Coastguard Worker wrapped[i]->setRelease(releaseProc, &freed[i]);
1640*c8dee2aaSAndroid Build Coastguard Worker }
1641*c8dee2aaSAndroid Build Coastguard Worker
1642*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == (freed[0] + freed[1] + freed[2]));
1643*c8dee2aaSAndroid Build Coastguard Worker
1644*c8dee2aaSAndroid Build Coastguard Worker // This should free nothing since no messages were sent.
1645*c8dee2aaSAndroid Build Coastguard Worker cache->purgeAsNeeded();
1646*c8dee2aaSAndroid Build Coastguard Worker
1647*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == (freed[0] + freed[1] + freed[2]));
1648*c8dee2aaSAndroid Build Coastguard Worker
1649*c8dee2aaSAndroid Build Coastguard Worker // Send message to free the first resource
1650*c8dee2aaSAndroid Build Coastguard Worker GrResourceCache::ReturnResourceFromThread(std::move(wrapped[0]), dContext->directContextID());
1651*c8dee2aaSAndroid Build Coastguard Worker cache->purgeAsNeeded();
1652*c8dee2aaSAndroid Build Coastguard Worker
1653*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == (freed[0] + freed[1] + freed[2]));
1654*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == freed[0]);
1655*c8dee2aaSAndroid Build Coastguard Worker
1656*c8dee2aaSAndroid Build Coastguard Worker GrResourceCache::ReturnResourceFromThread(std::move(wrapped[2]), dContext->directContextID());
1657*c8dee2aaSAndroid Build Coastguard Worker cache->purgeAsNeeded();
1658*c8dee2aaSAndroid Build Coastguard Worker
1659*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 2 == (freed[0] + freed[1] + freed[2]));
1660*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == freed[1]);
1661*c8dee2aaSAndroid Build Coastguard Worker
1662*c8dee2aaSAndroid Build Coastguard Worker wrapped[1].reset();
1663*c8dee2aaSAndroid Build Coastguard Worker
1664*c8dee2aaSAndroid Build Coastguard Worker mock.reset();
1665*c8dee2aaSAndroid Build Coastguard Worker
1666*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 3 == (freed[0] + freed[1] + freed[2]));
1667*c8dee2aaSAndroid Build Coastguard Worker }
1668*c8dee2aaSAndroid Build Coastguard Worker
1669*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST(ResourceCacheMisc, reporter, /* options */, CtsEnforcement::kApiLevel_T) {
1670*c8dee2aaSAndroid Build Coastguard Worker // The below tests create their own mock contexts.
1671*c8dee2aaSAndroid Build Coastguard Worker test_no_key(reporter);
1672*c8dee2aaSAndroid Build Coastguard Worker test_purge_unlocked(reporter);
1673*c8dee2aaSAndroid Build Coastguard Worker test_purge_command_buffer_usage(reporter);
1674*c8dee2aaSAndroid Build Coastguard Worker test_budgeting(reporter);
1675*c8dee2aaSAndroid Build Coastguard Worker test_unbudgeted(reporter);
1676*c8dee2aaSAndroid Build Coastguard Worker test_unbudgeted_to_scratch(reporter);
1677*c8dee2aaSAndroid Build Coastguard Worker test_duplicate_unique_key(reporter);
1678*c8dee2aaSAndroid Build Coastguard Worker test_duplicate_scratch_key(reporter);
1679*c8dee2aaSAndroid Build Coastguard Worker test_remove_scratch_key(reporter);
1680*c8dee2aaSAndroid Build Coastguard Worker test_scratch_key_consistency(reporter);
1681*c8dee2aaSAndroid Build Coastguard Worker test_purge_invalidated(reporter);
1682*c8dee2aaSAndroid Build Coastguard Worker test_cache_chained_purge(reporter);
1683*c8dee2aaSAndroid Build Coastguard Worker test_timestamp_wrap(reporter);
1684*c8dee2aaSAndroid Build Coastguard Worker test_time_purge(reporter);
1685*c8dee2aaSAndroid Build Coastguard Worker test_partial_purge(reporter);
1686*c8dee2aaSAndroid Build Coastguard Worker test_custom_data(reporter);
1687*c8dee2aaSAndroid Build Coastguard Worker test_abandoned(reporter);
1688*c8dee2aaSAndroid Build Coastguard Worker test_tags(reporter);
1689*c8dee2aaSAndroid Build Coastguard Worker test_free_texture_messages(reporter);
1690*c8dee2aaSAndroid Build Coastguard Worker }
1691*c8dee2aaSAndroid Build Coastguard Worker
1692*c8dee2aaSAndroid Build Coastguard Worker // This simulates a portion of Chrome's context abandonment processing.
1693*c8dee2aaSAndroid Build Coastguard Worker // Please see: crbug.com/1011368 and crbug.com/1014993
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ResourceMessagesAfterAbandon,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)1694*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ResourceMessagesAfterAbandon,
1695*c8dee2aaSAndroid Build Coastguard Worker reporter,
1696*c8dee2aaSAndroid Build Coastguard Worker ctxInfo,
1697*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_T) {
1698*c8dee2aaSAndroid Build Coastguard Worker using namespace skgpu;
1699*c8dee2aaSAndroid Build Coastguard Worker
1700*c8dee2aaSAndroid Build Coastguard Worker auto dContext = ctxInfo.directContext();
1701*c8dee2aaSAndroid Build Coastguard Worker GrGpu* gpu = dContext->priv().getGpu();
1702*c8dee2aaSAndroid Build Coastguard Worker
1703*c8dee2aaSAndroid Build Coastguard Worker Protected isProtected = Protected(dContext->priv().caps()->supportsProtectedContent());
1704*c8dee2aaSAndroid Build Coastguard Worker
1705*c8dee2aaSAndroid Build Coastguard Worker GrBackendTexture backend = dContext->createBackendTexture(
1706*c8dee2aaSAndroid Build Coastguard Worker 16, 16, SkColorType::kRGBA_8888_SkColorType, skgpu::Mipmapped::kNo, GrRenderable::kNo,
1707*c8dee2aaSAndroid Build Coastguard Worker isProtected);
1708*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> tex = gpu->wrapBackendTexture(backend,
1709*c8dee2aaSAndroid Build Coastguard Worker GrWrapOwnership::kBorrow_GrWrapOwnership,
1710*c8dee2aaSAndroid Build Coastguard Worker GrWrapCacheable::kYes,
1711*c8dee2aaSAndroid Build Coastguard Worker GrIOType::kRead_GrIOType);
1712*c8dee2aaSAndroid Build Coastguard Worker
1713*c8dee2aaSAndroid Build Coastguard Worker auto releaseProc = [](void* ctx) {
1714*c8dee2aaSAndroid Build Coastguard Worker int* index = (int*) ctx;
1715*c8dee2aaSAndroid Build Coastguard Worker *index = 1;
1716*c8dee2aaSAndroid Build Coastguard Worker };
1717*c8dee2aaSAndroid Build Coastguard Worker
1718*c8dee2aaSAndroid Build Coastguard Worker int freed = 0;
1719*c8dee2aaSAndroid Build Coastguard Worker
1720*c8dee2aaSAndroid Build Coastguard Worker tex->setRelease(releaseProc, &freed);
1721*c8dee2aaSAndroid Build Coastguard Worker
1722*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 0 == freed);
1723*c8dee2aaSAndroid Build Coastguard Worker
1724*c8dee2aaSAndroid Build Coastguard Worker // We must delete the backend texture before abandoning the context in vulkan. We just do it
1725*c8dee2aaSAndroid Build Coastguard Worker // for all the backends for consistency.
1726*c8dee2aaSAndroid Build Coastguard Worker dContext->deleteBackendTexture(backend);
1727*c8dee2aaSAndroid Build Coastguard Worker dContext->abandonContext();
1728*c8dee2aaSAndroid Build Coastguard Worker
1729*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, 1 == freed);
1730*c8dee2aaSAndroid Build Coastguard Worker
1731*c8dee2aaSAndroid Build Coastguard Worker // In the past, creating this message could cause an exception due to
1732*c8dee2aaSAndroid Build Coastguard Worker // an un-safe pointer upcast from GrTexture* to GrGpuResource* through virtual inheritance
1733*c8dee2aaSAndroid Build Coastguard Worker // after deletion of tex.
1734*c8dee2aaSAndroid Build Coastguard Worker GrResourceCache::ReturnResourceFromThread(std::move(tex), dContext->directContextID());
1735*c8dee2aaSAndroid Build Coastguard Worker
1736*c8dee2aaSAndroid Build Coastguard Worker // This doesn't actually do anything but it does trigger us to read messages
1737*c8dee2aaSAndroid Build Coastguard Worker dContext->purgeUnlockedResources(GrPurgeResourceOptions::kAllResources);
1738*c8dee2aaSAndroid Build Coastguard Worker }
1739*c8dee2aaSAndroid Build Coastguard Worker
1740*c8dee2aaSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
make_normal_texture(GrResourceProvider * provider,GrRenderable renderable,SkISize dims,int sampleCnt)1741*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<GrTexture> make_normal_texture(GrResourceProvider* provider,
1742*c8dee2aaSAndroid Build Coastguard Worker GrRenderable renderable,
1743*c8dee2aaSAndroid Build Coastguard Worker SkISize dims,
1744*c8dee2aaSAndroid Build Coastguard Worker int sampleCnt) {
1745*c8dee2aaSAndroid Build Coastguard Worker auto format = provider->caps()->getDefaultBackendFormat(GrColorType::kRGBA_8888, renderable);
1746*c8dee2aaSAndroid Build Coastguard Worker return provider->createTexture(dims,
1747*c8dee2aaSAndroid Build Coastguard Worker format,
1748*c8dee2aaSAndroid Build Coastguard Worker GrTextureType::k2D,
1749*c8dee2aaSAndroid Build Coastguard Worker renderable,
1750*c8dee2aaSAndroid Build Coastguard Worker sampleCnt,
1751*c8dee2aaSAndroid Build Coastguard Worker skgpu::Mipmapped::kNo,
1752*c8dee2aaSAndroid Build Coastguard Worker skgpu::Budgeted::kYes,
1753*c8dee2aaSAndroid Build Coastguard Worker GrProtected::kNo,
1754*c8dee2aaSAndroid Build Coastguard Worker /*label=*/{});
1755*c8dee2aaSAndroid Build Coastguard Worker }
1756*c8dee2aaSAndroid Build Coastguard Worker
make_mipmap_proxy(GrRecordingContext * rContext,GrRenderable renderable,SkISize dims,int sampleCnt)1757*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<GrTextureProxy> make_mipmap_proxy(GrRecordingContext* rContext,
1758*c8dee2aaSAndroid Build Coastguard Worker GrRenderable renderable,
1759*c8dee2aaSAndroid Build Coastguard Worker SkISize dims,
1760*c8dee2aaSAndroid Build Coastguard Worker int sampleCnt) {
1761*c8dee2aaSAndroid Build Coastguard Worker GrProxyProvider* proxyProvider = rContext->priv().proxyProvider();
1762*c8dee2aaSAndroid Build Coastguard Worker const GrCaps* caps = rContext->priv().caps();
1763*c8dee2aaSAndroid Build Coastguard Worker
1764*c8dee2aaSAndroid Build Coastguard Worker
1765*c8dee2aaSAndroid Build Coastguard Worker const GrBackendFormat format = caps->getDefaultBackendFormat(GrColorType::kRGBA_8888,
1766*c8dee2aaSAndroid Build Coastguard Worker GrRenderable::kNo);
1767*c8dee2aaSAndroid Build Coastguard Worker
1768*c8dee2aaSAndroid Build Coastguard Worker return proxyProvider->createProxy(format,
1769*c8dee2aaSAndroid Build Coastguard Worker dims,
1770*c8dee2aaSAndroid Build Coastguard Worker renderable,
1771*c8dee2aaSAndroid Build Coastguard Worker sampleCnt,
1772*c8dee2aaSAndroid Build Coastguard Worker skgpu::Mipmapped::kYes,
1773*c8dee2aaSAndroid Build Coastguard Worker SkBackingFit::kExact,
1774*c8dee2aaSAndroid Build Coastguard Worker skgpu::Budgeted::kYes,
1775*c8dee2aaSAndroid Build Coastguard Worker GrProtected::kNo,
1776*c8dee2aaSAndroid Build Coastguard Worker /*label=*/{});
1777*c8dee2aaSAndroid Build Coastguard Worker }
1778*c8dee2aaSAndroid Build Coastguard Worker
1779*c8dee2aaSAndroid Build Coastguard Worker // Exercise GrSurface::gpuMemorySize for different combos of MSAA, RT-only,
1780*c8dee2aaSAndroid Build Coastguard Worker // Texture-only, both-RT-and-Texture and MIPmapped
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(GPUMemorySize,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)1781*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(GPUMemorySize,
1782*c8dee2aaSAndroid Build Coastguard Worker reporter,
1783*c8dee2aaSAndroid Build Coastguard Worker ctxInfo,
1784*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_T) {
1785*c8dee2aaSAndroid Build Coastguard Worker auto context = ctxInfo.directContext();
1786*c8dee2aaSAndroid Build Coastguard Worker GrResourceProvider* resourceProvider = context->priv().resourceProvider();
1787*c8dee2aaSAndroid Build Coastguard Worker const GrCaps* caps = context->priv().caps();
1788*c8dee2aaSAndroid Build Coastguard Worker
1789*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkISize kSize = {64, 64};
1790*c8dee2aaSAndroid Build Coastguard Worker static constexpr auto kArea = kSize.area();
1791*c8dee2aaSAndroid Build Coastguard Worker
1792*c8dee2aaSAndroid Build Coastguard Worker // Normal versions
1793*c8dee2aaSAndroid Build Coastguard Worker {
1794*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> tex;
1795*c8dee2aaSAndroid Build Coastguard Worker
1796*c8dee2aaSAndroid Build Coastguard Worker tex = make_normal_texture(resourceProvider, GrRenderable::kYes, kSize, 1);
1797*c8dee2aaSAndroid Build Coastguard Worker size_t size = tex->gpuMemorySize();
1798*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, kArea*4 == size);
1799*c8dee2aaSAndroid Build Coastguard Worker
1800*c8dee2aaSAndroid Build Coastguard Worker size_t sampleCount = (size_t)caps->getRenderTargetSampleCount(4, tex->backendFormat());
1801*c8dee2aaSAndroid Build Coastguard Worker if (sampleCount >= 4) {
1802*c8dee2aaSAndroid Build Coastguard Worker tex = make_normal_texture(resourceProvider, GrRenderable::kYes, kSize, sampleCount);
1803*c8dee2aaSAndroid Build Coastguard Worker size = tex->gpuMemorySize();
1804*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter,
1805*c8dee2aaSAndroid Build Coastguard Worker kArea*4 == size || // msaa4 failed
1806*c8dee2aaSAndroid Build Coastguard Worker kArea*4*sampleCount == size || // auto-resolving
1807*c8dee2aaSAndroid Build Coastguard Worker kArea*4*(sampleCount+1) == size); // explicit resolve buffer
1808*c8dee2aaSAndroid Build Coastguard Worker }
1809*c8dee2aaSAndroid Build Coastguard Worker
1810*c8dee2aaSAndroid Build Coastguard Worker tex = make_normal_texture(resourceProvider, GrRenderable::kNo, kSize, 1);
1811*c8dee2aaSAndroid Build Coastguard Worker size = tex->gpuMemorySize();
1812*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, kArea*4 == size);
1813*c8dee2aaSAndroid Build Coastguard Worker }
1814*c8dee2aaSAndroid Build Coastguard Worker
1815*c8dee2aaSAndroid Build Coastguard Worker // Mipmapped versions
1816*c8dee2aaSAndroid Build Coastguard Worker if (caps->mipmapSupport()) {
1817*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTextureProxy> proxy;
1818*c8dee2aaSAndroid Build Coastguard Worker
1819*c8dee2aaSAndroid Build Coastguard Worker proxy = make_mipmap_proxy(context, GrRenderable::kYes, kSize, 1);
1820*c8dee2aaSAndroid Build Coastguard Worker size_t size = proxy->gpuMemorySize();
1821*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, kArea*4 + (kArea*4)/3 == size);
1822*c8dee2aaSAndroid Build Coastguard Worker
1823*c8dee2aaSAndroid Build Coastguard Worker size_t sampleCount = (size_t)caps->getRenderTargetSampleCount(4, proxy->backendFormat());
1824*c8dee2aaSAndroid Build Coastguard Worker if (sampleCount >= 4) {
1825*c8dee2aaSAndroid Build Coastguard Worker proxy = make_mipmap_proxy(context, GrRenderable::kYes, kSize, sampleCount);
1826*c8dee2aaSAndroid Build Coastguard Worker size = proxy->gpuMemorySize();
1827*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter,
1828*c8dee2aaSAndroid Build Coastguard Worker kArea*4 + (kArea*4)/3 == size || // msaa4 failed
1829*c8dee2aaSAndroid Build Coastguard Worker kArea*4*sampleCount + (kArea*4)/3 == size || // auto-resolving
1830*c8dee2aaSAndroid Build Coastguard Worker kArea*4*(sampleCount+1) + (kArea*4)/3 == size); // explicit resolve buffer
1831*c8dee2aaSAndroid Build Coastguard Worker }
1832*c8dee2aaSAndroid Build Coastguard Worker
1833*c8dee2aaSAndroid Build Coastguard Worker proxy = make_mipmap_proxy(context, GrRenderable::kNo, kSize, 1);
1834*c8dee2aaSAndroid Build Coastguard Worker size = proxy->gpuMemorySize();
1835*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, kArea*4 + (kArea*4)/3 == size);
1836*c8dee2aaSAndroid Build Coastguard Worker }
1837*c8dee2aaSAndroid Build Coastguard Worker }
1838*c8dee2aaSAndroid Build Coastguard Worker
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(PurgeToMakeHeadroom,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)1839*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(PurgeToMakeHeadroom,
1840*c8dee2aaSAndroid Build Coastguard Worker reporter,
1841*c8dee2aaSAndroid Build Coastguard Worker ctxInfo,
1842*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_T) {
1843*c8dee2aaSAndroid Build Coastguard Worker constexpr size_t kTexSize = 16 * 16 * 4;
1844*c8dee2aaSAndroid Build Coastguard Worker
1845*c8dee2aaSAndroid Build Coastguard Worker auto dContext = ctxInfo.directContext();
1846*c8dee2aaSAndroid Build Coastguard Worker dContext->setResourceCacheLimit(2 * kTexSize);
1847*c8dee2aaSAndroid Build Coastguard Worker auto resourceProvider = dContext->priv().resourceProvider();
1848*c8dee2aaSAndroid Build Coastguard Worker auto resourceCache = dContext->priv().getResourceCache();
1849*c8dee2aaSAndroid Build Coastguard Worker for (bool success : { true, false }) {
1850*c8dee2aaSAndroid Build Coastguard Worker reporter->push(SkString(success ? "success" : "failure"));
1851*c8dee2aaSAndroid Build Coastguard Worker
1852*c8dee2aaSAndroid Build Coastguard Worker resourceCache->releaseAll();
1853*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getBudgetedResourceBytes() == 0);
1854*c8dee2aaSAndroid Build Coastguard Worker
1855*c8dee2aaSAndroid Build Coastguard Worker // Make one unpurgeable texture and one purgeable texture.
1856*c8dee2aaSAndroid Build Coastguard Worker auto lockedTex = make_normal_texture(resourceProvider, GrRenderable::kNo, {16, 16}, 1);
1857*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, lockedTex->gpuMemorySize() == kTexSize);
1858*c8dee2aaSAndroid Build Coastguard Worker
1859*c8dee2aaSAndroid Build Coastguard Worker // N.b. this surface is renderable so "reuseScratchTextures = false" won't mess us up.
1860*c8dee2aaSAndroid Build Coastguard Worker auto purgeableTex = make_normal_texture(resourceProvider, GrRenderable::kYes, {16, 16}, 1);
1861*c8dee2aaSAndroid Build Coastguard Worker if (success) {
1862*c8dee2aaSAndroid Build Coastguard Worker purgeableTex = nullptr;
1863*c8dee2aaSAndroid Build Coastguard Worker }
1864*c8dee2aaSAndroid Build Coastguard Worker
1865*c8dee2aaSAndroid Build Coastguard Worker size_t expectedPurgeable = success ? kTexSize : 0;
1866*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, expectedPurgeable == resourceCache->getPurgeableBytes(),
1867*c8dee2aaSAndroid Build Coastguard Worker "%zu vs %zu", expectedPurgeable, resourceCache->getPurgeableBytes());
1868*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, success == resourceCache->purgeToMakeHeadroom(kTexSize));
1869*c8dee2aaSAndroid Build Coastguard Worker size_t expectedBudgeted = success ? kTexSize : (2 * kTexSize);
1870*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, expectedBudgeted == resourceCache->getBudgetedResourceBytes(),
1871*c8dee2aaSAndroid Build Coastguard Worker "%zu vs %zu", expectedBudgeted, resourceCache->getBudgetedResourceBytes());
1872*c8dee2aaSAndroid Build Coastguard Worker reporter->pop();
1873*c8dee2aaSAndroid Build Coastguard Worker }
1874*c8dee2aaSAndroid Build Coastguard Worker }
1875*c8dee2aaSAndroid Build Coastguard Worker
1876*c8dee2aaSAndroid Build Coastguard Worker #if GR_GPU_STATS
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(OverbudgetFlush,reporter,ctxInfo)1877*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_MOCK_CONTEXT(OverbudgetFlush, reporter, ctxInfo) {
1878*c8dee2aaSAndroid Build Coastguard Worker auto context = ctxInfo.directContext();
1879*c8dee2aaSAndroid Build Coastguard Worker context->setResourceCacheLimit(1);
1880*c8dee2aaSAndroid Build Coastguard Worker
1881*c8dee2aaSAndroid Build Coastguard Worker // Helper that determines if cache is overbudget.
1882*c8dee2aaSAndroid Build Coastguard Worker auto overbudget = [context] {
1883*c8dee2aaSAndroid Build Coastguard Worker int uNum;
1884*c8dee2aaSAndroid Build Coastguard Worker size_t uSize;
1885*c8dee2aaSAndroid Build Coastguard Worker context->getResourceCacheUsage(&uNum, &uSize);
1886*c8dee2aaSAndroid Build Coastguard Worker size_t bSize = context->getResourceCacheLimit();
1887*c8dee2aaSAndroid Build Coastguard Worker return uSize > bSize;
1888*c8dee2aaSAndroid Build Coastguard Worker };
1889*c8dee2aaSAndroid Build Coastguard Worker
1890*c8dee2aaSAndroid Build Coastguard Worker // Helper that does a trivial draw to a surface.
1891*c8dee2aaSAndroid Build Coastguard Worker auto drawToSurf = [](SkSurface* surf) {
1892*c8dee2aaSAndroid Build Coastguard Worker surf->getCanvas()->drawRect(SkRect::MakeWH(1,1), SkPaint());
1893*c8dee2aaSAndroid Build Coastguard Worker };
1894*c8dee2aaSAndroid Build Coastguard Worker
1895*c8dee2aaSAndroid Build Coastguard Worker // Helper that checks whether a flush has occurred between calls.
1896*c8dee2aaSAndroid Build Coastguard Worker int baseFlushCount = 0;
1897*c8dee2aaSAndroid Build Coastguard Worker auto getFlushCountDelta = [context, &baseFlushCount]() {
1898*c8dee2aaSAndroid Build Coastguard Worker int cur = context->priv().getGpu()->stats()->numSubmitToGpus();
1899*c8dee2aaSAndroid Build Coastguard Worker int delta = cur - baseFlushCount;
1900*c8dee2aaSAndroid Build Coastguard Worker baseFlushCount = cur;
1901*c8dee2aaSAndroid Build Coastguard Worker return delta;
1902*c8dee2aaSAndroid Build Coastguard Worker };
1903*c8dee2aaSAndroid Build Coastguard Worker
1904*c8dee2aaSAndroid Build Coastguard Worker auto info = SkImageInfo::Make(10, 10, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
1905*c8dee2aaSAndroid Build Coastguard Worker auto surf1 = SkSurfaces::RenderTarget(context, skgpu::Budgeted::kYes, info, 1, nullptr);
1906*c8dee2aaSAndroid Build Coastguard Worker auto surf2 = SkSurfaces::RenderTarget(context, skgpu::Budgeted::kYes, info, 1, nullptr);
1907*c8dee2aaSAndroid Build Coastguard Worker
1908*c8dee2aaSAndroid Build Coastguard Worker drawToSurf(surf1.get());
1909*c8dee2aaSAndroid Build Coastguard Worker drawToSurf(surf2.get());
1910*c8dee2aaSAndroid Build Coastguard Worker
1911*c8dee2aaSAndroid Build Coastguard Worker // Flush each surface once to ensure that their backing stores are allocated.
1912*c8dee2aaSAndroid Build Coastguard Worker context->flushAndSubmit(surf1.get(), GrSyncCpu::kNo);
1913*c8dee2aaSAndroid Build Coastguard Worker context->flushAndSubmit(surf2.get(), GrSyncCpu::kNo);
1914*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, overbudget());
1915*c8dee2aaSAndroid Build Coastguard Worker getFlushCountDelta();
1916*c8dee2aaSAndroid Build Coastguard Worker
1917*c8dee2aaSAndroid Build Coastguard Worker // Nothing should be purgeable so drawing to either surface doesn't cause a flush.
1918*c8dee2aaSAndroid Build Coastguard Worker drawToSurf(surf1.get());
1919*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !getFlushCountDelta());
1920*c8dee2aaSAndroid Build Coastguard Worker drawToSurf(surf2.get());
1921*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !getFlushCountDelta());
1922*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, overbudget());
1923*c8dee2aaSAndroid Build Coastguard Worker
1924*c8dee2aaSAndroid Build Coastguard Worker // Make surf1 purgeable. Drawing to surf2 should flush.
1925*c8dee2aaSAndroid Build Coastguard Worker context->flushAndSubmit(surf1.get(), GrSyncCpu::kNo);
1926*c8dee2aaSAndroid Build Coastguard Worker surf1.reset();
1927*c8dee2aaSAndroid Build Coastguard Worker drawToSurf(surf2.get());
1928*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, getFlushCountDelta());
1929*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, overbudget());
1930*c8dee2aaSAndroid Build Coastguard Worker }
1931*c8dee2aaSAndroid Build Coastguard Worker #endif
1932