1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2022 Google LLC
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 "tests/Test.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBitmap.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImage.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Context.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Image.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Recorder.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Recording.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Surface.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkCanvasPriv.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Caps.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/ContextPriv.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Device.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/RecorderPriv.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Resource.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/ResourceCache.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/ResourceProvider.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/SharedContext.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Texture.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/TextureProxyView.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/TextureUtils.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "src/image/SkImage_Base.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "tools/Resources.h"
33*c8dee2aaSAndroid Build Coastguard Worker #include "tools/graphite/GraphiteTestContext.h"
34*c8dee2aaSAndroid Build Coastguard Worker
35*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu::graphite {
36*c8dee2aaSAndroid Build Coastguard Worker
37*c8dee2aaSAndroid Build Coastguard Worker class TestResource : public Resource {
38*c8dee2aaSAndroid Build Coastguard Worker public:
Make(const SharedContext * sharedContext,Ownership owned,skgpu::Budgeted budgeted,Shareable shareable,size_t gpuMemorySize=1)39*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<TestResource> Make(const SharedContext* sharedContext,
40*c8dee2aaSAndroid Build Coastguard Worker Ownership owned,
41*c8dee2aaSAndroid Build Coastguard Worker skgpu::Budgeted budgeted,
42*c8dee2aaSAndroid Build Coastguard Worker Shareable shareable,
43*c8dee2aaSAndroid Build Coastguard Worker size_t gpuMemorySize = 1) {
44*c8dee2aaSAndroid Build Coastguard Worker auto resource = sk_sp<TestResource>(new TestResource(sharedContext,
45*c8dee2aaSAndroid Build Coastguard Worker owned,
46*c8dee2aaSAndroid Build Coastguard Worker budgeted,
47*c8dee2aaSAndroid Build Coastguard Worker gpuMemorySize));
48*c8dee2aaSAndroid Build Coastguard Worker if (!resource) {
49*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
50*c8dee2aaSAndroid Build Coastguard Worker }
51*c8dee2aaSAndroid Build Coastguard Worker
52*c8dee2aaSAndroid Build Coastguard Worker GraphiteResourceKey key;
53*c8dee2aaSAndroid Build Coastguard Worker CreateKey(&key, shareable);
54*c8dee2aaSAndroid Build Coastguard Worker
55*c8dee2aaSAndroid Build Coastguard Worker resource->setKey(key);
56*c8dee2aaSAndroid Build Coastguard Worker return resource;
57*c8dee2aaSAndroid Build Coastguard Worker }
58*c8dee2aaSAndroid Build Coastguard Worker
getResourceType() const59*c8dee2aaSAndroid Build Coastguard Worker const char* getResourceType() const override { return "Test Resource"; }
60*c8dee2aaSAndroid Build Coastguard Worker
CreateKey(GraphiteResourceKey * key,Shareable shareable)61*c8dee2aaSAndroid Build Coastguard Worker static void CreateKey(GraphiteResourceKey* key, Shareable shareable) {
62*c8dee2aaSAndroid Build Coastguard Worker // Internally we assert that we don't make the same key twice where the only difference is
63*c8dee2aaSAndroid Build Coastguard Worker // shareable vs non-shareable. That allows us to now have Shareable be part of the Key's
64*c8dee2aaSAndroid Build Coastguard Worker // key. So here we make two different resource types so the keys will be different.
65*c8dee2aaSAndroid Build Coastguard Worker static const ResourceType kType = GraphiteResourceKey::GenerateResourceType();
66*c8dee2aaSAndroid Build Coastguard Worker static const ResourceType kShareableType = GraphiteResourceKey::GenerateResourceType();
67*c8dee2aaSAndroid Build Coastguard Worker ResourceType type = shareable == Shareable::kNo ? kType : kShareableType;
68*c8dee2aaSAndroid Build Coastguard Worker GraphiteResourceKey::Builder(key, type, 0, shareable);
69*c8dee2aaSAndroid Build Coastguard Worker }
70*c8dee2aaSAndroid Build Coastguard Worker
71*c8dee2aaSAndroid Build Coastguard Worker private:
TestResource(const SharedContext * sharedContext,Ownership owned,skgpu::Budgeted budgeted,size_t gpuMemorySize)72*c8dee2aaSAndroid Build Coastguard Worker TestResource(const SharedContext* sharedContext,
73*c8dee2aaSAndroid Build Coastguard Worker Ownership owned,
74*c8dee2aaSAndroid Build Coastguard Worker skgpu::Budgeted budgeted,
75*c8dee2aaSAndroid Build Coastguard Worker size_t gpuMemorySize)
76*c8dee2aaSAndroid Build Coastguard Worker : Resource(sharedContext, owned, budgeted, gpuMemorySize) {}
77*c8dee2aaSAndroid Build Coastguard Worker
freeGpuData()78*c8dee2aaSAndroid Build Coastguard Worker void freeGpuData() override {}
79*c8dee2aaSAndroid Build Coastguard Worker };
80*c8dee2aaSAndroid Build Coastguard Worker
create_image_data(const SkImageInfo & info)81*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkData> create_image_data(const SkImageInfo& info) {
82*c8dee2aaSAndroid Build Coastguard Worker const size_t rowBytes = info.minRowBytes();
83*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> data(SkData::MakeUninitialized(rowBytes * info.height()));
84*c8dee2aaSAndroid Build Coastguard Worker {
85*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bm;
86*c8dee2aaSAndroid Build Coastguard Worker bm.installPixels(info, data->writable_data(), rowBytes);
87*c8dee2aaSAndroid Build Coastguard Worker SkCanvas canvas(bm);
88*c8dee2aaSAndroid Build Coastguard Worker canvas.clear(SK_ColorRED);
89*c8dee2aaSAndroid Build Coastguard Worker }
90*c8dee2aaSAndroid Build Coastguard Worker return data;
91*c8dee2aaSAndroid Build Coastguard Worker }
92*c8dee2aaSAndroid Build Coastguard Worker
top_device_graphite_target_proxy(SkCanvas * canvas)93*c8dee2aaSAndroid Build Coastguard Worker static skgpu::graphite::TextureProxy* top_device_graphite_target_proxy(SkCanvas* canvas) {
94*c8dee2aaSAndroid Build Coastguard Worker if (auto gpuDevice = SkCanvasPriv::TopDevice(canvas)->asGraphiteDevice()) {
95*c8dee2aaSAndroid Build Coastguard Worker return gpuDevice->target();
96*c8dee2aaSAndroid Build Coastguard Worker }
97*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
98*c8dee2aaSAndroid Build Coastguard Worker }
99*c8dee2aaSAndroid Build Coastguard Worker
DEF_CONDITIONAL_GRAPHITE_TEST_FOR_ALL_CONTEXTS(GraphiteBudgetedResourcesTest,reporter,context,testContext,true,CtsEnforcement::kApiLevel_V)100*c8dee2aaSAndroid Build Coastguard Worker DEF_CONDITIONAL_GRAPHITE_TEST_FOR_ALL_CONTEXTS(GraphiteBudgetedResourcesTest,
101*c8dee2aaSAndroid Build Coastguard Worker reporter,
102*c8dee2aaSAndroid Build Coastguard Worker context,
103*c8dee2aaSAndroid Build Coastguard Worker testContext,
104*c8dee2aaSAndroid Build Coastguard Worker true,
105*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_V) {
106*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Recorder> recorder = context->makeRecorder();
107*c8dee2aaSAndroid Build Coastguard Worker ResourceProvider* resourceProvider = recorder->priv().resourceProvider();
108*c8dee2aaSAndroid Build Coastguard Worker ResourceCache* resourceCache = resourceProvider->resourceCache();
109*c8dee2aaSAndroid Build Coastguard Worker const SharedContext* sharedContext = resourceProvider->sharedContext();
110*c8dee2aaSAndroid Build Coastguard Worker
111*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 0);
112*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->numFindableResources() == 0);
113*c8dee2aaSAndroid Build Coastguard Worker
114*c8dee2aaSAndroid Build Coastguard Worker // Test making a non budgeted, non shareable resource.
115*c8dee2aaSAndroid Build Coastguard Worker auto resource = TestResource::Make(
116*c8dee2aaSAndroid Build Coastguard Worker sharedContext, Ownership::kOwned, skgpu::Budgeted::kNo, Shareable::kNo);
117*c8dee2aaSAndroid Build Coastguard Worker if (!resource) {
118*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Failed to make TestResource");
119*c8dee2aaSAndroid Build Coastguard Worker return;
120*c8dee2aaSAndroid Build Coastguard Worker }
121*c8dee2aaSAndroid Build Coastguard Worker Resource* resourcePtr = resource.get();
122*c8dee2aaSAndroid Build Coastguard Worker
123*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resource->budgeted() == skgpu::Budgeted::kNo);
124*c8dee2aaSAndroid Build Coastguard Worker resourceCache->insertResource(resourcePtr);
125*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 1);
126*c8dee2aaSAndroid Build Coastguard Worker // Resource is not shareable and we have a ref on it. Thus it shouldn't ben findable in the
127*c8dee2aaSAndroid Build Coastguard Worker // cache.
128*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->numFindableResources() == 0);
129*c8dee2aaSAndroid Build Coastguard Worker
130*c8dee2aaSAndroid Build Coastguard Worker // When we reset our TestResource it should go back into the cache since it can be used as a
131*c8dee2aaSAndroid Build Coastguard Worker // scratch texture (since it is not shareable). At that point the budget should be changed to
132*c8dee2aaSAndroid Build Coastguard Worker // skgpu::Budgeted::kYes.
133*c8dee2aaSAndroid Build Coastguard Worker resource.reset();
134*c8dee2aaSAndroid Build Coastguard Worker resourceCache->forceProcessReturnedResources();
135*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 1);
136*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->numFindableResources() == 1);
137*c8dee2aaSAndroid Build Coastguard Worker // Even though we reset our ref on the resource we still have the ptr to it and should be the
138*c8dee2aaSAndroid Build Coastguard Worker // resource in the cache. So in general this is dangerous it should be safe for this test to
139*c8dee2aaSAndroid Build Coastguard Worker // directly access the texture.
140*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourcePtr->budgeted() == skgpu::Budgeted::kYes);
141*c8dee2aaSAndroid Build Coastguard Worker
142*c8dee2aaSAndroid Build Coastguard Worker GraphiteResourceKey key;
143*c8dee2aaSAndroid Build Coastguard Worker TestResource::CreateKey(&key, Shareable::kNo);
144*c8dee2aaSAndroid Build Coastguard Worker Resource* resourcePtr2 = resourceCache->findAndRefResource(key, skgpu::Budgeted::kNo);
145*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourcePtr == resourcePtr2);
146*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 1);
147*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->numFindableResources() == 0);
148*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourcePtr2->budgeted() == skgpu::Budgeted::kNo);
149*c8dee2aaSAndroid Build Coastguard Worker resourcePtr2->unref();
150*c8dee2aaSAndroid Build Coastguard Worker resourceCache->forceProcessReturnedResources();
151*c8dee2aaSAndroid Build Coastguard Worker
152*c8dee2aaSAndroid Build Coastguard Worker // Test making a budgeted, shareable resource.
153*c8dee2aaSAndroid Build Coastguard Worker resource = TestResource::Make(
154*c8dee2aaSAndroid Build Coastguard Worker sharedContext, Ownership::kOwned, skgpu::Budgeted::kYes, Shareable::kYes);
155*c8dee2aaSAndroid Build Coastguard Worker if (!resource) {
156*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Failed to make TestResource");
157*c8dee2aaSAndroid Build Coastguard Worker return;
158*c8dee2aaSAndroid Build Coastguard Worker }
159*c8dee2aaSAndroid Build Coastguard Worker resourcePtr = resource.get();
160*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resource->budgeted() == skgpu::Budgeted::kYes);
161*c8dee2aaSAndroid Build Coastguard Worker resourceCache->insertResource(resourcePtr);
162*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 2);
163*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->numFindableResources() == 2);
164*c8dee2aaSAndroid Build Coastguard Worker
165*c8dee2aaSAndroid Build Coastguard Worker resource.reset();
166*c8dee2aaSAndroid Build Coastguard Worker resourceCache->forceProcessReturnedResources();
167*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 2);
168*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->numFindableResources() == 2);
169*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourcePtr->budgeted() == skgpu::Budgeted::kYes);
170*c8dee2aaSAndroid Build Coastguard Worker
171*c8dee2aaSAndroid Build Coastguard Worker TestResource::CreateKey(&key, Shareable::kYes);
172*c8dee2aaSAndroid Build Coastguard Worker resourcePtr2 = resourceCache->findAndRefResource(key, skgpu::Budgeted::kYes);
173*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourcePtr == resourcePtr2);
174*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 2);
175*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->numFindableResources() == 2);
176*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourcePtr2->budgeted() == skgpu::Budgeted::kYes);
177*c8dee2aaSAndroid Build Coastguard Worker resourcePtr2->unref();
178*c8dee2aaSAndroid Build Coastguard Worker
179*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////////////////////
180*c8dee2aaSAndroid Build Coastguard Worker // Test that SkImage's and SkSurface's underlying Resource's follow the expected budgeted
181*c8dee2aaSAndroid Build Coastguard Worker // system.
182*c8dee2aaSAndroid Build Coastguard Worker auto info = SkImageInfo::Make(10, 10, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
183*c8dee2aaSAndroid Build Coastguard Worker
184*c8dee2aaSAndroid Build Coastguard Worker // First test SkImages. Since we can't directly create a Graphite SkImage we first have to make
185*c8dee2aaSAndroid Build Coastguard Worker // a raster SkImage than convert that to a Graphite SkImage via makeTextureImage.
186*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> data(create_image_data(info));
187*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> image = SkImages::RasterFromData(info, std::move(data), info.minRowBytes());
188*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, image);
189*c8dee2aaSAndroid Build Coastguard Worker
190*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> imageGpu = SkImages::TextureFromImage(recorder.get(), image, {});
191*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, imageGpu);
192*c8dee2aaSAndroid Build Coastguard Worker
193*c8dee2aaSAndroid Build Coastguard Worker TextureProxy* imageProxy = nullptr;
194*c8dee2aaSAndroid Build Coastguard Worker {
195*c8dee2aaSAndroid Build Coastguard Worker // We don't want the view holding a ref to the Proxy or else we can't send things back to
196*c8dee2aaSAndroid Build Coastguard Worker // the cache.
197*c8dee2aaSAndroid Build Coastguard Worker auto view = skgpu::graphite::AsView(imageGpu.get());
198*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, view);
199*c8dee2aaSAndroid Build Coastguard Worker imageProxy = view.proxy();
200*c8dee2aaSAndroid Build Coastguard Worker }
201*c8dee2aaSAndroid Build Coastguard Worker // Make sure the proxy is instantiated
202*c8dee2aaSAndroid Build Coastguard Worker if (!imageProxy->instantiate(resourceProvider)) {
203*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Failed to instantiate Proxy");
204*c8dee2aaSAndroid Build Coastguard Worker return;
205*c8dee2aaSAndroid Build Coastguard Worker }
206*c8dee2aaSAndroid Build Coastguard Worker const Resource* imageResourcePtr = imageProxy->texture();
207*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, imageResourcePtr);
208*c8dee2aaSAndroid Build Coastguard Worker // There is an extra resource for the buffer that is uploading the data to the texture
209*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 4);
210*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->numFindableResources() == 2);
211*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, imageResourcePtr->budgeted() == skgpu::Budgeted::kNo);
212*c8dee2aaSAndroid Build Coastguard Worker
213*c8dee2aaSAndroid Build Coastguard Worker // Submit all upload work so we can drop refs to the image and get it returned to the cache.
214*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Recording> recording = recorder->snap();
215*c8dee2aaSAndroid Build Coastguard Worker if (!recording) {
216*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Failed to make recording");
217*c8dee2aaSAndroid Build Coastguard Worker return;
218*c8dee2aaSAndroid Build Coastguard Worker }
219*c8dee2aaSAndroid Build Coastguard Worker InsertRecordingInfo insertInfo;
220*c8dee2aaSAndroid Build Coastguard Worker insertInfo.fRecording = recording.get();
221*c8dee2aaSAndroid Build Coastguard Worker context->insertRecording(insertInfo);
222*c8dee2aaSAndroid Build Coastguard Worker testContext->syncedSubmit(context);
223*c8dee2aaSAndroid Build Coastguard Worker recording.reset();
224*c8dee2aaSAndroid Build Coastguard Worker imageGpu.reset();
225*c8dee2aaSAndroid Build Coastguard Worker resourceCache->forceProcessReturnedResources();
226*c8dee2aaSAndroid Build Coastguard Worker
227*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 4);
228*c8dee2aaSAndroid Build Coastguard Worker // Remapping async buffers before returning them to the cache can extend buffer lifetime.
229*c8dee2aaSAndroid Build Coastguard Worker if (!context->priv().caps()->bufferMapsAreAsync()) {
230*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->numFindableResources() == 4);
231*c8dee2aaSAndroid Build Coastguard Worker }
232*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, imageResourcePtr->budgeted() == skgpu::Budgeted::kYes);
233*c8dee2aaSAndroid Build Coastguard Worker
234*c8dee2aaSAndroid Build Coastguard Worker // Now try an SkSurface. This is simpler since we can directly create Graphite SkSurface's.
235*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(recorder.get(), info);
236*c8dee2aaSAndroid Build Coastguard Worker if (!surface) {
237*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Failed to make surface");
238*c8dee2aaSAndroid Build Coastguard Worker return;
239*c8dee2aaSAndroid Build Coastguard Worker }
240*c8dee2aaSAndroid Build Coastguard Worker
241*c8dee2aaSAndroid Build Coastguard Worker TextureProxy* surfaceProxy = top_device_graphite_target_proxy(surface->getCanvas());
242*c8dee2aaSAndroid Build Coastguard Worker if (!surfaceProxy) {
243*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Failed to get surface proxy");
244*c8dee2aaSAndroid Build Coastguard Worker return;
245*c8dee2aaSAndroid Build Coastguard Worker }
246*c8dee2aaSAndroid Build Coastguard Worker
247*c8dee2aaSAndroid Build Coastguard Worker // Make sure the proxy is instantiated
248*c8dee2aaSAndroid Build Coastguard Worker if (!surfaceProxy->instantiate(resourceProvider)) {
249*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Failed to instantiate surface proxy");
250*c8dee2aaSAndroid Build Coastguard Worker return;
251*c8dee2aaSAndroid Build Coastguard Worker }
252*c8dee2aaSAndroid Build Coastguard Worker const Resource* surfaceResourcePtr = surfaceProxy->texture();
253*c8dee2aaSAndroid Build Coastguard Worker
254*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 5);
255*c8dee2aaSAndroid Build Coastguard Worker // Remapping async buffers before returning them to the cache can extend buffer lifetime.
256*c8dee2aaSAndroid Build Coastguard Worker if (!context->priv().caps()->bufferMapsAreAsync()) {
257*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->numFindableResources() == 4);
258*c8dee2aaSAndroid Build Coastguard Worker }
259*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, surfaceResourcePtr->budgeted() == skgpu::Budgeted::kNo);
260*c8dee2aaSAndroid Build Coastguard Worker
261*c8dee2aaSAndroid Build Coastguard Worker // The creation of the surface may have added an initial clear to it. Thus if we just reset the
262*c8dee2aaSAndroid Build Coastguard Worker // surface it will flush the clean on the device and we don't be dropping all our refs to the
263*c8dee2aaSAndroid Build Coastguard Worker // surface. So we force all the work to happen first.
264*c8dee2aaSAndroid Build Coastguard Worker recording = recorder->snap();
265*c8dee2aaSAndroid Build Coastguard Worker insertInfo.fRecording = recording.get();
266*c8dee2aaSAndroid Build Coastguard Worker context->insertRecording(insertInfo);
267*c8dee2aaSAndroid Build Coastguard Worker testContext->syncedSubmit(context);
268*c8dee2aaSAndroid Build Coastguard Worker recording.reset();
269*c8dee2aaSAndroid Build Coastguard Worker
270*c8dee2aaSAndroid Build Coastguard Worker surface.reset();
271*c8dee2aaSAndroid Build Coastguard Worker resourceCache->forceProcessReturnedResources();
272*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, surfaceResourcePtr->budgeted() == skgpu::Budgeted::kYes);
273*c8dee2aaSAndroid Build Coastguard Worker }
274*c8dee2aaSAndroid Build Coastguard Worker
275*c8dee2aaSAndroid Build Coastguard Worker namespace {
add_new_resource(skiatest::Reporter * reporter,const SharedContext * sharedContext,ResourceCache * resourceCache,size_t gpuMemorySize,skgpu::Budgeted budgeted=skgpu::Budgeted::kYes)276*c8dee2aaSAndroid Build Coastguard Worker sk_sp<Resource> add_new_resource(skiatest::Reporter* reporter,
277*c8dee2aaSAndroid Build Coastguard Worker const SharedContext* sharedContext,
278*c8dee2aaSAndroid Build Coastguard Worker ResourceCache* resourceCache,
279*c8dee2aaSAndroid Build Coastguard Worker size_t gpuMemorySize,
280*c8dee2aaSAndroid Build Coastguard Worker skgpu::Budgeted budgeted = skgpu::Budgeted::kYes) {
281*c8dee2aaSAndroid Build Coastguard Worker auto resource = TestResource::Make(sharedContext,
282*c8dee2aaSAndroid Build Coastguard Worker Ownership::kOwned,
283*c8dee2aaSAndroid Build Coastguard Worker budgeted,
284*c8dee2aaSAndroid Build Coastguard Worker Shareable::kNo,
285*c8dee2aaSAndroid Build Coastguard Worker gpuMemorySize);
286*c8dee2aaSAndroid Build Coastguard Worker if (!resource) {
287*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Failed to make TestResource");
288*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
289*c8dee2aaSAndroid Build Coastguard Worker }
290*c8dee2aaSAndroid Build Coastguard Worker resourceCache->insertResource(resource.get());
291*c8dee2aaSAndroid Build Coastguard Worker return resource;
292*c8dee2aaSAndroid Build Coastguard Worker }
293*c8dee2aaSAndroid Build Coastguard Worker
add_new_purgeable_resource(skiatest::Reporter * reporter,const SharedContext * sharedContext,ResourceCache * resourceCache,size_t gpuMemorySize)294*c8dee2aaSAndroid Build Coastguard Worker Resource* add_new_purgeable_resource(skiatest::Reporter* reporter,
295*c8dee2aaSAndroid Build Coastguard Worker const SharedContext* sharedContext,
296*c8dee2aaSAndroid Build Coastguard Worker ResourceCache* resourceCache,
297*c8dee2aaSAndroid Build Coastguard Worker size_t gpuMemorySize) {
298*c8dee2aaSAndroid Build Coastguard Worker auto resource = add_new_resource(reporter, sharedContext, resourceCache, gpuMemorySize);
299*c8dee2aaSAndroid Build Coastguard Worker if (!resource) {
300*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
301*c8dee2aaSAndroid Build Coastguard Worker }
302*c8dee2aaSAndroid Build Coastguard Worker
303*c8dee2aaSAndroid Build Coastguard Worker Resource* ptr = resource.get();
304*c8dee2aaSAndroid Build Coastguard Worker resource.reset();
305*c8dee2aaSAndroid Build Coastguard Worker resourceCache->forceProcessReturnedResources();
306*c8dee2aaSAndroid Build Coastguard Worker return ptr;
307*c8dee2aaSAndroid Build Coastguard Worker }
308*c8dee2aaSAndroid Build Coastguard Worker } // namespace
309*c8dee2aaSAndroid Build Coastguard Worker
DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(GraphitePurgeAsNeededResourcesTest,reporter,context,CtsEnforcement::kApiLevel_V)310*c8dee2aaSAndroid Build Coastguard Worker DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(GraphitePurgeAsNeededResourcesTest, reporter, context,
311*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_V) {
312*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Recorder> recorder = context->makeRecorder();
313*c8dee2aaSAndroid Build Coastguard Worker ResourceProvider* resourceProvider = recorder->priv().resourceProvider();
314*c8dee2aaSAndroid Build Coastguard Worker ResourceCache* resourceCache = resourceProvider->resourceCache();
315*c8dee2aaSAndroid Build Coastguard Worker const SharedContext* sharedContext = resourceProvider->sharedContext();
316*c8dee2aaSAndroid Build Coastguard Worker
317*c8dee2aaSAndroid Build Coastguard Worker resourceCache->setMaxBudget(10);
318*c8dee2aaSAndroid Build Coastguard Worker
319*c8dee2aaSAndroid Build Coastguard Worker auto resourceSize10 = add_new_resource(reporter,
320*c8dee2aaSAndroid Build Coastguard Worker sharedContext,
321*c8dee2aaSAndroid Build Coastguard Worker resourceCache,
322*c8dee2aaSAndroid Build Coastguard Worker /*gpuMemorySize=*/10);
323*c8dee2aaSAndroid Build Coastguard Worker
324*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 1);
325*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->topOfPurgeableQueue() == nullptr);
326*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->currentBudgetedBytes() == 10);
327*c8dee2aaSAndroid Build Coastguard Worker
328*c8dee2aaSAndroid Build Coastguard Worker auto resourceSize1 = add_new_resource(reporter,
329*c8dee2aaSAndroid Build Coastguard Worker sharedContext,
330*c8dee2aaSAndroid Build Coastguard Worker resourceCache,
331*c8dee2aaSAndroid Build Coastguard Worker /*gpuMemorySize=*/1);
332*c8dee2aaSAndroid Build Coastguard Worker
333*c8dee2aaSAndroid Build Coastguard Worker // We should now be over budget, but nothing should be purged since neither resource is
334*c8dee2aaSAndroid Build Coastguard Worker // purgeable.
335*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 2);
336*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->topOfPurgeableQueue() == nullptr);
337*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->currentBudgetedBytes() == 11);
338*c8dee2aaSAndroid Build Coastguard Worker
339*c8dee2aaSAndroid Build Coastguard Worker // Dropping the ref to the size 1 resource should cause it to get purged when we add a new
340*c8dee2aaSAndroid Build Coastguard Worker // resource to the cache.
341*c8dee2aaSAndroid Build Coastguard Worker resourceSize1.reset();
342*c8dee2aaSAndroid Build Coastguard Worker
343*c8dee2aaSAndroid Build Coastguard Worker auto resourceSize2 = add_new_resource(reporter,
344*c8dee2aaSAndroid Build Coastguard Worker sharedContext,
345*c8dee2aaSAndroid Build Coastguard Worker resourceCache,
346*c8dee2aaSAndroid Build Coastguard Worker /*gpuMemorySize=*/2);
347*c8dee2aaSAndroid Build Coastguard Worker
348*c8dee2aaSAndroid Build Coastguard Worker // The purging should have happened when we return the resource above so we also shouldn't
349*c8dee2aaSAndroid Build Coastguard Worker // see anything in the purgeable queue.
350*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 2);
351*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->topOfPurgeableQueue() == nullptr);
352*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->currentBudgetedBytes() == 12);
353*c8dee2aaSAndroid Build Coastguard Worker
354*c8dee2aaSAndroid Build Coastguard Worker // Reset the cache back to no resources by setting budget to 0.
355*c8dee2aaSAndroid Build Coastguard Worker resourceSize10.reset();
356*c8dee2aaSAndroid Build Coastguard Worker resourceSize2.reset();
357*c8dee2aaSAndroid Build Coastguard Worker resourceCache->forceProcessReturnedResources();
358*c8dee2aaSAndroid Build Coastguard Worker resourceCache->setMaxBudget(0);
359*c8dee2aaSAndroid Build Coastguard Worker
360*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 0);
361*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->topOfPurgeableQueue() == nullptr);
362*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->currentBudgetedBytes() == 0);
363*c8dee2aaSAndroid Build Coastguard Worker
364*c8dee2aaSAndroid Build Coastguard Worker // Add a bunch of purgeable resources that keeps us under budget. Nothing should ever get purged.
365*c8dee2aaSAndroid Build Coastguard Worker resourceCache->setMaxBudget(10);
366*c8dee2aaSAndroid Build Coastguard Worker auto resourceSize1Ptr = add_new_purgeable_resource(reporter,
367*c8dee2aaSAndroid Build Coastguard Worker sharedContext,
368*c8dee2aaSAndroid Build Coastguard Worker resourceCache,
369*c8dee2aaSAndroid Build Coastguard Worker /*gpuMemorySize=*/1);
370*c8dee2aaSAndroid Build Coastguard Worker /*auto resourceSize2Ptr=*/ add_new_purgeable_resource(reporter,
371*c8dee2aaSAndroid Build Coastguard Worker sharedContext,
372*c8dee2aaSAndroid Build Coastguard Worker resourceCache,
373*c8dee2aaSAndroid Build Coastguard Worker /*gpuMemorySize=*/2);
374*c8dee2aaSAndroid Build Coastguard Worker auto resourceSize3Ptr = add_new_purgeable_resource(reporter,
375*c8dee2aaSAndroid Build Coastguard Worker sharedContext,
376*c8dee2aaSAndroid Build Coastguard Worker resourceCache,
377*c8dee2aaSAndroid Build Coastguard Worker /*gpuMemorySize=*/3);
378*c8dee2aaSAndroid Build Coastguard Worker auto resourceSize4Ptr = add_new_purgeable_resource(reporter,
379*c8dee2aaSAndroid Build Coastguard Worker sharedContext,
380*c8dee2aaSAndroid Build Coastguard Worker resourceCache,
381*c8dee2aaSAndroid Build Coastguard Worker /*gpuMemorySize=*/4);
382*c8dee2aaSAndroid Build Coastguard Worker
383*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 4);
384*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->topOfPurgeableQueue() == resourceSize1Ptr);
385*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->currentBudgetedBytes() == 10);
386*c8dee2aaSAndroid Build Coastguard Worker
387*c8dee2aaSAndroid Build Coastguard Worker // Now add some resources that should cause things to get purged.
388*c8dee2aaSAndroid Build Coastguard Worker // Add a size 2 resource should purge the original size 1 and size 2
389*c8dee2aaSAndroid Build Coastguard Worker add_new_purgeable_resource(reporter,
390*c8dee2aaSAndroid Build Coastguard Worker sharedContext,
391*c8dee2aaSAndroid Build Coastguard Worker resourceCache,
392*c8dee2aaSAndroid Build Coastguard Worker /*gpuMemorySize=*/2);
393*c8dee2aaSAndroid Build Coastguard Worker
394*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 3);
395*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->topOfPurgeableQueue() == resourceSize3Ptr);
396*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->currentBudgetedBytes() == 9);
397*c8dee2aaSAndroid Build Coastguard Worker
398*c8dee2aaSAndroid Build Coastguard Worker // Adding a non-purgeable resource should also trigger resources to be purged from purgeable
399*c8dee2aaSAndroid Build Coastguard Worker // queue.
400*c8dee2aaSAndroid Build Coastguard Worker resourceSize10 = add_new_resource(reporter,
401*c8dee2aaSAndroid Build Coastguard Worker sharedContext,
402*c8dee2aaSAndroid Build Coastguard Worker resourceCache,
403*c8dee2aaSAndroid Build Coastguard Worker /*gpuMemorySize=*/10);
404*c8dee2aaSAndroid Build Coastguard Worker
405*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 1);
406*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->topOfPurgeableQueue() == nullptr);
407*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->currentBudgetedBytes() == 10);
408*c8dee2aaSAndroid Build Coastguard Worker
409*c8dee2aaSAndroid Build Coastguard Worker // Adding a resources that is purgeable back to the cache shouldn't trigger the previous
410*c8dee2aaSAndroid Build Coastguard Worker // non-purgeable resource or itself to be purged yet (since processing our return mailbox
411*c8dee2aaSAndroid Build Coastguard Worker // doesn't trigger the purgeAsNeeded call)
412*c8dee2aaSAndroid Build Coastguard Worker resourceSize4Ptr = add_new_purgeable_resource(reporter,
413*c8dee2aaSAndroid Build Coastguard Worker sharedContext,
414*c8dee2aaSAndroid Build Coastguard Worker resourceCache,
415*c8dee2aaSAndroid Build Coastguard Worker /*gpuMemorySize=*/4);
416*c8dee2aaSAndroid Build Coastguard Worker
417*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 2);
418*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->topOfPurgeableQueue() == resourceSize4Ptr);
419*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->currentBudgetedBytes() == 14);
420*c8dee2aaSAndroid Build Coastguard Worker
421*c8dee2aaSAndroid Build Coastguard Worker // Resetting the budget to 0 should trigger purging the size 4 purgeable resource but should
422*c8dee2aaSAndroid Build Coastguard Worker // leave the non purgeable size 10 alone.
423*c8dee2aaSAndroid Build Coastguard Worker resourceCache->setMaxBudget(0);
424*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 1);
425*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->topOfPurgeableQueue() == nullptr);
426*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->currentBudgetedBytes() == 10);
427*c8dee2aaSAndroid Build Coastguard Worker
428*c8dee2aaSAndroid Build Coastguard Worker resourceSize10.reset();
429*c8dee2aaSAndroid Build Coastguard Worker resourceCache->forceProcessReturnedResources();
430*c8dee2aaSAndroid Build Coastguard Worker resourceCache->forcePurgeAsNeeded();
431*c8dee2aaSAndroid Build Coastguard Worker
432*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 0);
433*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->topOfPurgeableQueue() == nullptr);
434*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->currentBudgetedBytes() == 0);
435*c8dee2aaSAndroid Build Coastguard Worker }
436*c8dee2aaSAndroid Build Coastguard Worker
DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(GraphiteZeroSizedResourcesTest,reporter,context,CtsEnforcement::kApiLevel_V)437*c8dee2aaSAndroid Build Coastguard Worker DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(GraphiteZeroSizedResourcesTest, reporter, context,
438*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_V) {
439*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Recorder> recorder = context->makeRecorder();
440*c8dee2aaSAndroid Build Coastguard Worker ResourceProvider* resourceProvider = recorder->priv().resourceProvider();
441*c8dee2aaSAndroid Build Coastguard Worker ResourceCache* resourceCache = resourceProvider->resourceCache();
442*c8dee2aaSAndroid Build Coastguard Worker const SharedContext* sharedContext = resourceProvider->sharedContext();
443*c8dee2aaSAndroid Build Coastguard Worker
444*c8dee2aaSAndroid Build Coastguard Worker // First make a normal resource that has a non zero size
445*c8dee2aaSAndroid Build Coastguard Worker Resource* resourcePtr = add_new_purgeable_resource(reporter,
446*c8dee2aaSAndroid Build Coastguard Worker sharedContext,
447*c8dee2aaSAndroid Build Coastguard Worker resourceCache,
448*c8dee2aaSAndroid Build Coastguard Worker /*gpuMemorySize=*/1);
449*c8dee2aaSAndroid Build Coastguard Worker if (!resourcePtr) {
450*c8dee2aaSAndroid Build Coastguard Worker return;
451*c8dee2aaSAndroid Build Coastguard Worker }
452*c8dee2aaSAndroid Build Coastguard Worker
453*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 1);
454*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->numFindableResources() == 1);
455*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->topOfPurgeableQueue() == resourcePtr);
456*c8dee2aaSAndroid Build Coastguard Worker
457*c8dee2aaSAndroid Build Coastguard Worker // First confirm if we set the max budget to zero, this sized resource is removed.
458*c8dee2aaSAndroid Build Coastguard Worker resourceCache->setMaxBudget(0);
459*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 0);
460*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->numFindableResources() == 0);
461*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->topOfPurgeableQueue() == nullptr);
462*c8dee2aaSAndroid Build Coastguard Worker
463*c8dee2aaSAndroid Build Coastguard Worker // Set the budget back to something higher
464*c8dee2aaSAndroid Build Coastguard Worker resourceCache->setMaxBudget(100);
465*c8dee2aaSAndroid Build Coastguard Worker
466*c8dee2aaSAndroid Build Coastguard Worker // Now create a zero sized resource and add it to the cache.
467*c8dee2aaSAndroid Build Coastguard Worker resourcePtr = add_new_purgeable_resource(reporter,
468*c8dee2aaSAndroid Build Coastguard Worker sharedContext,
469*c8dee2aaSAndroid Build Coastguard Worker resourceCache,
470*c8dee2aaSAndroid Build Coastguard Worker /*gpuMemorySize=*/0);
471*c8dee2aaSAndroid Build Coastguard Worker if (!resourcePtr) {
472*c8dee2aaSAndroid Build Coastguard Worker return;
473*c8dee2aaSAndroid Build Coastguard Worker }
474*c8dee2aaSAndroid Build Coastguard Worker
475*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 1);
476*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->numFindableResources() == 1);
477*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->topOfPurgeableQueue() == resourcePtr);
478*c8dee2aaSAndroid Build Coastguard Worker
479*c8dee2aaSAndroid Build Coastguard Worker // Setting the budget down to 0 should not cause the zero sized resource to be purged
480*c8dee2aaSAndroid Build Coastguard Worker resourceCache->setMaxBudget(0);
481*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 1);
482*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->numFindableResources() == 1);
483*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->topOfPurgeableQueue() == resourcePtr);
484*c8dee2aaSAndroid Build Coastguard Worker
485*c8dee2aaSAndroid Build Coastguard Worker // Now add a sized resource to cache. Set budget higher again so that it fits
486*c8dee2aaSAndroid Build Coastguard Worker resourceCache->setMaxBudget(100);
487*c8dee2aaSAndroid Build Coastguard Worker
488*c8dee2aaSAndroid Build Coastguard Worker Resource* sizedResourcePtr = add_new_purgeable_resource(reporter,
489*c8dee2aaSAndroid Build Coastguard Worker sharedContext,
490*c8dee2aaSAndroid Build Coastguard Worker resourceCache,
491*c8dee2aaSAndroid Build Coastguard Worker /*gpuMemorySize=*/1);
492*c8dee2aaSAndroid Build Coastguard Worker if (!resourcePtr) {
493*c8dee2aaSAndroid Build Coastguard Worker return;
494*c8dee2aaSAndroid Build Coastguard Worker }
495*c8dee2aaSAndroid Build Coastguard Worker
496*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 2);
497*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->numFindableResources() == 2);
498*c8dee2aaSAndroid Build Coastguard Worker // Even though the zero sized resource was added to the cache first, the top of the purgeable
499*c8dee2aaSAndroid Build Coastguard Worker // stack should be the sized resource.
500*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->topOfPurgeableQueue() == sizedResourcePtr);
501*c8dee2aaSAndroid Build Coastguard Worker
502*c8dee2aaSAndroid Build Coastguard Worker // Add another zero sized resource
503*c8dee2aaSAndroid Build Coastguard Worker resourcePtr = add_new_purgeable_resource(reporter,
504*c8dee2aaSAndroid Build Coastguard Worker sharedContext,
505*c8dee2aaSAndroid Build Coastguard Worker resourceCache,
506*c8dee2aaSAndroid Build Coastguard Worker /*gpuMemorySize=*/0);
507*c8dee2aaSAndroid Build Coastguard Worker if (!resourcePtr) {
508*c8dee2aaSAndroid Build Coastguard Worker return;
509*c8dee2aaSAndroid Build Coastguard Worker }
510*c8dee2aaSAndroid Build Coastguard Worker
511*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 3);
512*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->numFindableResources() == 3);
513*c8dee2aaSAndroid Build Coastguard Worker // Again the sized resource should still be the top of the purgeable queue
514*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->topOfPurgeableQueue() == sizedResourcePtr);
515*c8dee2aaSAndroid Build Coastguard Worker
516*c8dee2aaSAndroid Build Coastguard Worker // If we set the cache budget to 0, it should clear out the sized resource but leave the two
517*c8dee2aaSAndroid Build Coastguard Worker // zero-sized resources.
518*c8dee2aaSAndroid Build Coastguard Worker resourceCache->setMaxBudget(0);
519*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 2);
520*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->numFindableResources() == 2);
521*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->topOfPurgeableQueue()->gpuMemorySize() == 0);
522*c8dee2aaSAndroid Build Coastguard Worker
523*c8dee2aaSAndroid Build Coastguard Worker // However, purging all resources should clear the zero-sized resources.
524*c8dee2aaSAndroid Build Coastguard Worker resourceCache->purgeResources();
525*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 0);
526*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->numFindableResources() == 0);
527*c8dee2aaSAndroid Build Coastguard Worker }
528*c8dee2aaSAndroid Build Coastguard Worker
529*c8dee2aaSAndroid Build Coastguard Worker // Depending on the granularity of the clock for a given device, in the
530*c8dee2aaSAndroid Build Coastguard Worker // GraphitePurgeNotUsedSinceResourcesTest we may end up with times that are all equal which messes
531*c8dee2aaSAndroid Build Coastguard Worker // up the expected behavior of the purge calls. So this helper forces us to return a new time that
532*c8dee2aaSAndroid Build Coastguard Worker // is different from a previous one.
force_newer_timepoint(const skgpu::StdSteadyClock::time_point & prevTime)533*c8dee2aaSAndroid Build Coastguard Worker skgpu::StdSteadyClock::time_point force_newer_timepoint(
534*c8dee2aaSAndroid Build Coastguard Worker const skgpu::StdSteadyClock::time_point& prevTime) {
535*c8dee2aaSAndroid Build Coastguard Worker auto time = skgpu::StdSteadyClock::now();
536*c8dee2aaSAndroid Build Coastguard Worker while (time <= prevTime) {
537*c8dee2aaSAndroid Build Coastguard Worker time = skgpu::StdSteadyClock::now();
538*c8dee2aaSAndroid Build Coastguard Worker }
539*c8dee2aaSAndroid Build Coastguard Worker return time;
540*c8dee2aaSAndroid Build Coastguard Worker }
541*c8dee2aaSAndroid Build Coastguard Worker
DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(GraphitePurgeNotUsedSinceResourcesTest,reporter,context,CtsEnforcement::kApiLevel_V)542*c8dee2aaSAndroid Build Coastguard Worker DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(GraphitePurgeNotUsedSinceResourcesTest, reporter, context,
543*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_V) {
544*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Recorder> recorder = context->makeRecorder();
545*c8dee2aaSAndroid Build Coastguard Worker ResourceProvider* resourceProvider = recorder->priv().resourceProvider();
546*c8dee2aaSAndroid Build Coastguard Worker ResourceCache* resourceCache = resourceProvider->resourceCache();
547*c8dee2aaSAndroid Build Coastguard Worker const SharedContext* sharedContext = resourceProvider->sharedContext();
548*c8dee2aaSAndroid Build Coastguard Worker
549*c8dee2aaSAndroid Build Coastguard Worker // Basic test where we purge 1 resource
550*c8dee2aaSAndroid Build Coastguard Worker auto beforeTime = skgpu::StdSteadyClock::now();
551*c8dee2aaSAndroid Build Coastguard Worker
552*c8dee2aaSAndroid Build Coastguard Worker auto resourcePtr = add_new_purgeable_resource(reporter,
553*c8dee2aaSAndroid Build Coastguard Worker sharedContext,
554*c8dee2aaSAndroid Build Coastguard Worker resourceCache,
555*c8dee2aaSAndroid Build Coastguard Worker /*gpuMemorySize=*/1);
556*c8dee2aaSAndroid Build Coastguard Worker if (!resourcePtr) {
557*c8dee2aaSAndroid Build Coastguard Worker return;
558*c8dee2aaSAndroid Build Coastguard Worker }
559*c8dee2aaSAndroid Build Coastguard Worker
560*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 1);
561*c8dee2aaSAndroid Build Coastguard Worker
562*c8dee2aaSAndroid Build Coastguard Worker auto afterTime = force_newer_timepoint(skgpu::StdSteadyClock::now());
563*c8dee2aaSAndroid Build Coastguard Worker
564*c8dee2aaSAndroid Build Coastguard Worker // purging beforeTime should not get rid of the resource
565*c8dee2aaSAndroid Build Coastguard Worker resourceCache->purgeResourcesNotUsedSince(beforeTime);
566*c8dee2aaSAndroid Build Coastguard Worker
567*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 1);
568*c8dee2aaSAndroid Build Coastguard Worker
569*c8dee2aaSAndroid Build Coastguard Worker // purging at afterTime which is after resource became purgeable should purge it.
570*c8dee2aaSAndroid Build Coastguard Worker resourceCache->purgeResourcesNotUsedSince(afterTime);
571*c8dee2aaSAndroid Build Coastguard Worker
572*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 0);
573*c8dee2aaSAndroid Build Coastguard Worker
574*c8dee2aaSAndroid Build Coastguard Worker // Test making 2 purgeable resources, but asking to purge on a time between the two.
575*c8dee2aaSAndroid Build Coastguard Worker Resource* resourcePtr1 = add_new_purgeable_resource(reporter,
576*c8dee2aaSAndroid Build Coastguard Worker sharedContext,
577*c8dee2aaSAndroid Build Coastguard Worker resourceCache,
578*c8dee2aaSAndroid Build Coastguard Worker /*gpuMemorySize=*/1);
579*c8dee2aaSAndroid Build Coastguard Worker
580*c8dee2aaSAndroid Build Coastguard Worker auto betweenTime = force_newer_timepoint(skgpu::StdSteadyClock::now());
581*c8dee2aaSAndroid Build Coastguard Worker
582*c8dee2aaSAndroid Build Coastguard Worker Resource* resourcePtr2 = add_new_purgeable_resource(reporter,
583*c8dee2aaSAndroid Build Coastguard Worker sharedContext,
584*c8dee2aaSAndroid Build Coastguard Worker resourceCache,
585*c8dee2aaSAndroid Build Coastguard Worker /*gpuMemorySize=*/1);
586*c8dee2aaSAndroid Build Coastguard Worker
587*c8dee2aaSAndroid Build Coastguard Worker afterTime = force_newer_timepoint(skgpu::StdSteadyClock::now());
588*c8dee2aaSAndroid Build Coastguard Worker
589*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 2);
590*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->testingInPurgeableQueue(resourcePtr1));
591*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->testingInPurgeableQueue(resourcePtr2));
592*c8dee2aaSAndroid Build Coastguard Worker
593*c8dee2aaSAndroid Build Coastguard Worker resourceCache->purgeResourcesNotUsedSince(betweenTime);
594*c8dee2aaSAndroid Build Coastguard Worker
595*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 1);
596*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->testingInPurgeableQueue(resourcePtr2));
597*c8dee2aaSAndroid Build Coastguard Worker
598*c8dee2aaSAndroid Build Coastguard Worker resourceCache->purgeResourcesNotUsedSince(afterTime);
599*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 0);
600*c8dee2aaSAndroid Build Coastguard Worker
601*c8dee2aaSAndroid Build Coastguard Worker // purgeResourcesNotUsedSince should have no impact on non-purgeable resources
602*c8dee2aaSAndroid Build Coastguard Worker auto resource = add_new_resource(reporter,
603*c8dee2aaSAndroid Build Coastguard Worker sharedContext,
604*c8dee2aaSAndroid Build Coastguard Worker resourceCache,
605*c8dee2aaSAndroid Build Coastguard Worker /*gpuMemorySize=*/1);
606*c8dee2aaSAndroid Build Coastguard Worker if (!resource) {
607*c8dee2aaSAndroid Build Coastguard Worker return;
608*c8dee2aaSAndroid Build Coastguard Worker }
609*c8dee2aaSAndroid Build Coastguard Worker resourcePtr = resource.get();
610*c8dee2aaSAndroid Build Coastguard Worker
611*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 1);
612*c8dee2aaSAndroid Build Coastguard Worker
613*c8dee2aaSAndroid Build Coastguard Worker afterTime = force_newer_timepoint(skgpu::StdSteadyClock::now());
614*c8dee2aaSAndroid Build Coastguard Worker resourceCache->purgeResourcesNotUsedSince(afterTime);
615*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 1);
616*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !resourceCache->testingInPurgeableQueue(resourcePtr));
617*c8dee2aaSAndroid Build Coastguard Worker
618*c8dee2aaSAndroid Build Coastguard Worker resource.reset();
619*c8dee2aaSAndroid Build Coastguard Worker // purgeResourcesNotUsedSince should check the mailbox for the returned resource. Though the
620*c8dee2aaSAndroid Build Coastguard Worker // time is set before that happens so nothing should purge.
621*c8dee2aaSAndroid Build Coastguard Worker resourceCache->purgeResourcesNotUsedSince(skgpu::StdSteadyClock::now());
622*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 1);
623*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->testingInPurgeableQueue(resourcePtr));
624*c8dee2aaSAndroid Build Coastguard Worker
625*c8dee2aaSAndroid Build Coastguard Worker // Now it should be purged since it is already purgeable
626*c8dee2aaSAndroid Build Coastguard Worker resourceCache->purgeResourcesNotUsedSince(force_newer_timepoint(skgpu::StdSteadyClock::now()));
627*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 0);
628*c8dee2aaSAndroid Build Coastguard Worker }
629*c8dee2aaSAndroid Build Coastguard Worker
630*c8dee2aaSAndroid Build Coastguard Worker // This test is used to check the case where we call purgeNotUsedSince, which triggers us to return
631*c8dee2aaSAndroid Build Coastguard Worker // resources from mailbox. Even though the returned resources aren't purged by the last used, we
632*c8dee2aaSAndroid Build Coastguard Worker // still end up purging things to get under budget.
DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(GraphitePurgeNotUsedOverBudgetTest,reporter,context,CtsEnforcement::kApiLevel_V)633*c8dee2aaSAndroid Build Coastguard Worker DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(GraphitePurgeNotUsedOverBudgetTest, reporter, context,
634*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_V) {
635*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Recorder> recorder = context->makeRecorder();
636*c8dee2aaSAndroid Build Coastguard Worker ResourceProvider* resourceProvider = recorder->priv().resourceProvider();
637*c8dee2aaSAndroid Build Coastguard Worker ResourceCache* resourceCache = resourceProvider->resourceCache();
638*c8dee2aaSAndroid Build Coastguard Worker const SharedContext* sharedContext = resourceProvider->sharedContext();
639*c8dee2aaSAndroid Build Coastguard Worker
640*c8dee2aaSAndroid Build Coastguard Worker // set resourceCache budget to 10 for testing.
641*c8dee2aaSAndroid Build Coastguard Worker resourceCache->setMaxBudget(10);
642*c8dee2aaSAndroid Build Coastguard Worker
643*c8dee2aaSAndroid Build Coastguard Worker // First make a purgeable resources
644*c8dee2aaSAndroid Build Coastguard Worker auto resourcePtr = add_new_purgeable_resource(reporter,
645*c8dee2aaSAndroid Build Coastguard Worker sharedContext,
646*c8dee2aaSAndroid Build Coastguard Worker resourceCache,
647*c8dee2aaSAndroid Build Coastguard Worker /*gpuMemorySize=*/1);
648*c8dee2aaSAndroid Build Coastguard Worker if (!resourcePtr) {
649*c8dee2aaSAndroid Build Coastguard Worker return;
650*c8dee2aaSAndroid Build Coastguard Worker }
651*c8dee2aaSAndroid Build Coastguard Worker
652*c8dee2aaSAndroid Build Coastguard Worker // Now create a bunch of non purgeable (yet) resources that are not budgeted (i.e. in real world
653*c8dee2aaSAndroid Build Coastguard Worker // they would be wrapped in an SkSurface or SkImage), but will cause us to go over our budget
654*c8dee2aaSAndroid Build Coastguard Worker // limit when they do return to cache.
655*c8dee2aaSAndroid Build Coastguard Worker
656*c8dee2aaSAndroid Build Coastguard Worker auto resource1 = add_new_resource(reporter,
657*c8dee2aaSAndroid Build Coastguard Worker sharedContext,
658*c8dee2aaSAndroid Build Coastguard Worker resourceCache,
659*c8dee2aaSAndroid Build Coastguard Worker /*gpuMemorySize=*/15,
660*c8dee2aaSAndroid Build Coastguard Worker skgpu::Budgeted::kNo);
661*c8dee2aaSAndroid Build Coastguard Worker
662*c8dee2aaSAndroid Build Coastguard Worker auto resource2 = add_new_resource(reporter,
663*c8dee2aaSAndroid Build Coastguard Worker sharedContext,
664*c8dee2aaSAndroid Build Coastguard Worker resourceCache,
665*c8dee2aaSAndroid Build Coastguard Worker /*gpuMemorySize=*/16,
666*c8dee2aaSAndroid Build Coastguard Worker skgpu::Budgeted::kNo);
667*c8dee2aaSAndroid Build Coastguard Worker
668*c8dee2aaSAndroid Build Coastguard Worker auto resource3 = add_new_resource(reporter,
669*c8dee2aaSAndroid Build Coastguard Worker sharedContext,
670*c8dee2aaSAndroid Build Coastguard Worker resourceCache,
671*c8dee2aaSAndroid Build Coastguard Worker /*gpuMemorySize=*/3,
672*c8dee2aaSAndroid Build Coastguard Worker skgpu::Budgeted::kNo);
673*c8dee2aaSAndroid Build Coastguard Worker
674*c8dee2aaSAndroid Build Coastguard Worker auto resource1Ptr = resource1.get();
675*c8dee2aaSAndroid Build Coastguard Worker auto resource2Ptr = resource2.get();
676*c8dee2aaSAndroid Build Coastguard Worker auto resource3Ptr = resource3.get();
677*c8dee2aaSAndroid Build Coastguard Worker
678*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 4);
679*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->currentBudgetedBytes() == 1);
680*c8dee2aaSAndroid Build Coastguard Worker
681*c8dee2aaSAndroid Build Coastguard Worker auto timeBeforeReturningToCache = skgpu::StdSteadyClock::now();
682*c8dee2aaSAndroid Build Coastguard Worker
683*c8dee2aaSAndroid Build Coastguard Worker // Now reset all the non budgeted resources so they return to the cache and become budgeted.
684*c8dee2aaSAndroid Build Coastguard Worker // Returning to the cache will not immedidately trigger a purgeAsNeededCall.
685*c8dee2aaSAndroid Build Coastguard Worker resource1.reset();
686*c8dee2aaSAndroid Build Coastguard Worker resource2.reset();
687*c8dee2aaSAndroid Build Coastguard Worker resource3.reset();
688*c8dee2aaSAndroid Build Coastguard Worker
689*c8dee2aaSAndroid Build Coastguard Worker resourceCache->forceProcessReturnedResources();
690*c8dee2aaSAndroid Build Coastguard Worker
691*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 4);
692*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->currentBudgetedBytes() == 35);
693*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->testingInPurgeableQueue(resourcePtr));
694*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->testingInPurgeableQueue(resource1Ptr));
695*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->testingInPurgeableQueue(resource2Ptr));
696*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->testingInPurgeableQueue(resource3Ptr));
697*c8dee2aaSAndroid Build Coastguard Worker
698*c8dee2aaSAndroid Build Coastguard Worker // Now we call purgeNotUsedSince with timeBeforeReturnToCache. The original resource should get
699*c8dee2aaSAndroid Build Coastguard Worker // purged because it is older than this time. The three originally non budgeted resources are
700*c8dee2aaSAndroid Build Coastguard Worker // newer than this time so they won't be purged by the time on this call. However, since we are
701*c8dee2aaSAndroid Build Coastguard Worker // overbudget it should trigger us to purge the first two of these resources to get us back
702*c8dee2aaSAndroid Build Coastguard Worker // under.
703*c8dee2aaSAndroid Build Coastguard Worker resourceCache->purgeResourcesNotUsedSince(timeBeforeReturningToCache);
704*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 1);
705*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->currentBudgetedBytes() == 3);
706*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->testingInPurgeableQueue(resource3Ptr));
707*c8dee2aaSAndroid Build Coastguard Worker }
708*c8dee2aaSAndroid Build Coastguard Worker
709*c8dee2aaSAndroid Build Coastguard Worker // Test call purgeResources on the ResourceCache and make sure all unlocked resources are getting
710*c8dee2aaSAndroid Build Coastguard Worker // purged regardless of when they were last used.
DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(GraphitePurgeResourcesTest,reporter,context,CtsEnforcement::kApiLevel_V)711*c8dee2aaSAndroid Build Coastguard Worker DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(GraphitePurgeResourcesTest, reporter, context,
712*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_V) {
713*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Recorder> recorder = context->makeRecorder();
714*c8dee2aaSAndroid Build Coastguard Worker ResourceProvider* resourceProvider = recorder->priv().resourceProvider();
715*c8dee2aaSAndroid Build Coastguard Worker ResourceCache* resourceCache = resourceProvider->resourceCache();
716*c8dee2aaSAndroid Build Coastguard Worker const SharedContext* sharedContext = resourceProvider->sharedContext();
717*c8dee2aaSAndroid Build Coastguard Worker
718*c8dee2aaSAndroid Build Coastguard Worker // set resourceCache budget to 10 for testing.
719*c8dee2aaSAndroid Build Coastguard Worker resourceCache->setMaxBudget(10);
720*c8dee2aaSAndroid Build Coastguard Worker
721*c8dee2aaSAndroid Build Coastguard Worker // Basic test where we purge 1 resource
722*c8dee2aaSAndroid Build Coastguard Worker auto resourcePtr = add_new_purgeable_resource(reporter,
723*c8dee2aaSAndroid Build Coastguard Worker sharedContext,
724*c8dee2aaSAndroid Build Coastguard Worker resourceCache,
725*c8dee2aaSAndroid Build Coastguard Worker /*gpuMemorySize=*/1);
726*c8dee2aaSAndroid Build Coastguard Worker if (!resourcePtr) {
727*c8dee2aaSAndroid Build Coastguard Worker return;
728*c8dee2aaSAndroid Build Coastguard Worker }
729*c8dee2aaSAndroid Build Coastguard Worker
730*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 1);
731*c8dee2aaSAndroid Build Coastguard Worker
732*c8dee2aaSAndroid Build Coastguard Worker // purging should purge the one unlocked resource.
733*c8dee2aaSAndroid Build Coastguard Worker resourceCache->purgeResources();
734*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 0);
735*c8dee2aaSAndroid Build Coastguard Worker
736*c8dee2aaSAndroid Build Coastguard Worker // Test making 2 purgeable resources
737*c8dee2aaSAndroid Build Coastguard Worker Resource* resourcePtr1 = add_new_purgeable_resource(reporter,
738*c8dee2aaSAndroid Build Coastguard Worker sharedContext,
739*c8dee2aaSAndroid Build Coastguard Worker resourceCache,
740*c8dee2aaSAndroid Build Coastguard Worker /*gpuMemorySize=*/1);
741*c8dee2aaSAndroid Build Coastguard Worker
742*c8dee2aaSAndroid Build Coastguard Worker Resource* resourcePtr2 = add_new_purgeable_resource(reporter,
743*c8dee2aaSAndroid Build Coastguard Worker sharedContext,
744*c8dee2aaSAndroid Build Coastguard Worker resourceCache,
745*c8dee2aaSAndroid Build Coastguard Worker /*gpuMemorySize=*/1);
746*c8dee2aaSAndroid Build Coastguard Worker if (!resourcePtr1 || !resourcePtr2) {
747*c8dee2aaSAndroid Build Coastguard Worker return;
748*c8dee2aaSAndroid Build Coastguard Worker }
749*c8dee2aaSAndroid Build Coastguard Worker
750*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 2);
751*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->testingInPurgeableQueue(resourcePtr1));
752*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->testingInPurgeableQueue(resourcePtr2));
753*c8dee2aaSAndroid Build Coastguard Worker
754*c8dee2aaSAndroid Build Coastguard Worker resourceCache->purgeResources();
755*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 0);
756*c8dee2aaSAndroid Build Coastguard Worker
757*c8dee2aaSAndroid Build Coastguard Worker // purgeResources should have no impact on non-purgeable resources
758*c8dee2aaSAndroid Build Coastguard Worker auto resource = add_new_resource(reporter,
759*c8dee2aaSAndroid Build Coastguard Worker sharedContext,
760*c8dee2aaSAndroid Build Coastguard Worker resourceCache,
761*c8dee2aaSAndroid Build Coastguard Worker /*gpuMemorySize=*/1);
762*c8dee2aaSAndroid Build Coastguard Worker if (!resource) {
763*c8dee2aaSAndroid Build Coastguard Worker return;
764*c8dee2aaSAndroid Build Coastguard Worker }
765*c8dee2aaSAndroid Build Coastguard Worker resourcePtr = resource.get();
766*c8dee2aaSAndroid Build Coastguard Worker
767*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 1);
768*c8dee2aaSAndroid Build Coastguard Worker
769*c8dee2aaSAndroid Build Coastguard Worker resourceCache->purgeResources();
770*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 1);
771*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !resourceCache->testingInPurgeableQueue(resourcePtr));
772*c8dee2aaSAndroid Build Coastguard Worker
773*c8dee2aaSAndroid Build Coastguard Worker resource.reset();
774*c8dee2aaSAndroid Build Coastguard Worker resourceCache->purgeResources();
775*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, resourceCache->getResourceCount() == 0);
776*c8dee2aaSAndroid Build Coastguard Worker }
777*c8dee2aaSAndroid Build Coastguard Worker
778*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu::graphite
779