1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2017 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci// This is a GPU-backend specific test.
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "tests/Test.h"
11cb93a386Sopenharmony_ci
12cb93a386Sopenharmony_ci#include "include/core/SkBitmap.h"
13cb93a386Sopenharmony_ci#include "include/core/SkImage.h"
14cb93a386Sopenharmony_ci#include "include/gpu/GrBackendSurface.h"
15cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h"
16cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h"
17cb93a386Sopenharmony_ci#include "src/gpu/GrProxyProvider.h"
18cb93a386Sopenharmony_ci#include "src/gpu/GrRecordingContextPriv.h"
19cb93a386Sopenharmony_ci#include "src/gpu/GrResourceCache.h"
20cb93a386Sopenharmony_ci#include "src/gpu/GrResourceProvider.h"
21cb93a386Sopenharmony_ci#include "src/gpu/GrTexture.h"
22cb93a386Sopenharmony_ci#include "src/gpu/GrTextureProxy.h"
23cb93a386Sopenharmony_ci#include "src/gpu/SkGr.h"
24cb93a386Sopenharmony_ci#include "tools/gpu/ManagedBackendTexture.h"
25cb93a386Sopenharmony_ci
26cb93a386Sopenharmony_ci#ifdef SK_DAWN
27cb93a386Sopenharmony_ci#include "src/gpu/dawn/GrDawnGpu.h"
28cb93a386Sopenharmony_ci#endif
29cb93a386Sopenharmony_ci
30cb93a386Sopenharmony_ciint GrProxyProvider::numUniqueKeyProxies_TestOnly() const {
31cb93a386Sopenharmony_ci    return fUniquelyKeyedProxies.count();
32cb93a386Sopenharmony_ci}
33cb93a386Sopenharmony_ci
34cb93a386Sopenharmony_cistatic constexpr auto kColorType = GrColorType::kRGBA_8888;
35cb93a386Sopenharmony_cistatic constexpr auto kSize = SkISize::Make(64, 64);
36cb93a386Sopenharmony_ci
37cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////////////////////////
38cb93a386Sopenharmony_ci// Basic test
39cb93a386Sopenharmony_ci
40cb93a386Sopenharmony_cistatic sk_sp<GrTextureProxy> deferred_tex(skiatest::Reporter* reporter,
41cb93a386Sopenharmony_ci                                          GrRecordingContext* rContext,
42cb93a386Sopenharmony_ci                                          GrProxyProvider* proxyProvider,
43cb93a386Sopenharmony_ci                                          SkBackingFit fit) {
44cb93a386Sopenharmony_ci    const GrCaps* caps = rContext->priv().caps();
45cb93a386Sopenharmony_ci
46cb93a386Sopenharmony_ci    GrBackendFormat format = caps->getDefaultBackendFormat(kColorType, GrRenderable::kNo);
47cb93a386Sopenharmony_ci
48cb93a386Sopenharmony_ci    sk_sp<GrTextureProxy> proxy =
49cb93a386Sopenharmony_ci            proxyProvider->createProxy(format, kSize, GrRenderable::kNo, 1, GrMipmapped::kNo, fit,
50cb93a386Sopenharmony_ci                                       SkBudgeted::kYes, GrProtected::kNo);
51cb93a386Sopenharmony_ci    // Only budgeted & wrapped external proxies get to carry uniqueKeys
52cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, !proxy->getUniqueKey().isValid());
53cb93a386Sopenharmony_ci    return proxy;
54cb93a386Sopenharmony_ci}
55cb93a386Sopenharmony_ci
56cb93a386Sopenharmony_cistatic sk_sp<GrTextureProxy> deferred_texRT(skiatest::Reporter* reporter,
57cb93a386Sopenharmony_ci                                            GrRecordingContext* rContext,
58cb93a386Sopenharmony_ci                                            GrProxyProvider* proxyProvider,
59cb93a386Sopenharmony_ci                                            SkBackingFit fit) {
60cb93a386Sopenharmony_ci    const GrCaps* caps = rContext->priv().caps();
61cb93a386Sopenharmony_ci
62cb93a386Sopenharmony_ci    GrBackendFormat format = caps->getDefaultBackendFormat(kColorType, GrRenderable::kYes);
63cb93a386Sopenharmony_ci
64cb93a386Sopenharmony_ci    sk_sp<GrTextureProxy> proxy =
65cb93a386Sopenharmony_ci            proxyProvider->createProxy(format, kSize, GrRenderable::kYes, 1, GrMipmapped::kNo, fit,
66cb93a386Sopenharmony_ci                                       SkBudgeted::kYes, GrProtected::kNo);
67cb93a386Sopenharmony_ci    // Only budgeted & wrapped external proxies get to carry uniqueKeys
68cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, !proxy->getUniqueKey().isValid());
69cb93a386Sopenharmony_ci    return proxy;
70cb93a386Sopenharmony_ci}
71cb93a386Sopenharmony_ci
72cb93a386Sopenharmony_cistatic sk_sp<GrTextureProxy> wrapped(skiatest::Reporter* reporter, GrRecordingContext*,
73cb93a386Sopenharmony_ci                                     GrProxyProvider* proxyProvider, SkBackingFit fit) {
74cb93a386Sopenharmony_ci    sk_sp<GrTextureProxy> proxy = proxyProvider->testingOnly_createInstantiatedProxy(
75cb93a386Sopenharmony_ci            kSize, kColorType, GrRenderable::kNo, 1, fit, SkBudgeted::kYes, GrProtected::kNo);
76cb93a386Sopenharmony_ci    // Only budgeted & wrapped external proxies get to carry uniqueKeys
77cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, !proxy->getUniqueKey().isValid());
78cb93a386Sopenharmony_ci    return proxy;
79cb93a386Sopenharmony_ci}
80cb93a386Sopenharmony_ci
81cb93a386Sopenharmony_cistatic sk_sp<GrTextureProxy> wrapped_with_key(skiatest::Reporter* reporter, GrRecordingContext*,
82cb93a386Sopenharmony_ci                                              GrProxyProvider* proxyProvider, SkBackingFit fit) {
83cb93a386Sopenharmony_ci    static GrUniqueKey::Domain d = GrUniqueKey::GenerateDomain();
84cb93a386Sopenharmony_ci    static int kUniqueKeyData = 0;
85cb93a386Sopenharmony_ci
86cb93a386Sopenharmony_ci    GrUniqueKey key;
87cb93a386Sopenharmony_ci
88cb93a386Sopenharmony_ci    GrUniqueKey::Builder builder(&key, d, 1, nullptr);
89cb93a386Sopenharmony_ci    builder[0] = kUniqueKeyData++;
90cb93a386Sopenharmony_ci    builder.finish();
91cb93a386Sopenharmony_ci
92cb93a386Sopenharmony_ci    // Only budgeted & wrapped external proxies get to carry uniqueKeys
93cb93a386Sopenharmony_ci    sk_sp<GrTextureProxy> proxy = proxyProvider->testingOnly_createInstantiatedProxy(
94cb93a386Sopenharmony_ci            kSize, kColorType, GrRenderable::kNo, 1, fit, SkBudgeted::kYes, GrProtected::kNo);
95cb93a386Sopenharmony_ci    SkAssertResult(proxyProvider->assignUniqueKeyToProxy(key, proxy.get()));
96cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, proxy->getUniqueKey().isValid());
97cb93a386Sopenharmony_ci    return proxy;
98cb93a386Sopenharmony_ci}
99cb93a386Sopenharmony_ci
100cb93a386Sopenharmony_cistatic sk_sp<GrTextureProxy> create_wrapped_backend(GrDirectContext* dContext) {
101cb93a386Sopenharmony_ci    auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(
102cb93a386Sopenharmony_ci            dContext,
103cb93a386Sopenharmony_ci            kSize.width(),
104cb93a386Sopenharmony_ci            kSize.height(),
105cb93a386Sopenharmony_ci            GrColorTypeToSkColorType(kColorType),
106cb93a386Sopenharmony_ci            GrMipmapped::kNo,
107cb93a386Sopenharmony_ci            GrRenderable::kNo,
108cb93a386Sopenharmony_ci            GrProtected::kNo);
109cb93a386Sopenharmony_ci    if (!mbet) {
110cb93a386Sopenharmony_ci        return nullptr;
111cb93a386Sopenharmony_ci    }
112cb93a386Sopenharmony_ci    GrProxyProvider* proxyProvider = dContext->priv().proxyProvider();
113cb93a386Sopenharmony_ci    return proxyProvider->wrapBackendTexture(mbet->texture(),
114cb93a386Sopenharmony_ci                                             kBorrow_GrWrapOwnership,
115cb93a386Sopenharmony_ci                                             GrWrapCacheable::kYes,
116cb93a386Sopenharmony_ci                                             kRead_GrIOType,
117cb93a386Sopenharmony_ci                                             mbet->refCountedCallback());
118cb93a386Sopenharmony_ci}
119cb93a386Sopenharmony_ci
120cb93a386Sopenharmony_ci// This tests the basic capabilities of the uniquely keyed texture proxies. Does assigning
121cb93a386Sopenharmony_ci// and looking them up work, etc.
122cb93a386Sopenharmony_cistatic void basic_test(GrDirectContext* dContext,
123cb93a386Sopenharmony_ci                       skiatest::Reporter* reporter,
124cb93a386Sopenharmony_ci                       sk_sp<GrTextureProxy> proxy,
125cb93a386Sopenharmony_ci                       int cacheEntriesPerProxy) {
126cb93a386Sopenharmony_ci    static int id = 1;
127cb93a386Sopenharmony_ci
128cb93a386Sopenharmony_ci    GrResourceProvider* resourceProvider = dContext->priv().resourceProvider();
129cb93a386Sopenharmony_ci    GrProxyProvider* proxyProvider = dContext->priv().proxyProvider();
130cb93a386Sopenharmony_ci    GrResourceCache* cache = dContext->priv().getResourceCache();
131cb93a386Sopenharmony_ci
132cb93a386Sopenharmony_ci    int startCacheCount = cache->getResourceCount();
133cb93a386Sopenharmony_ci
134cb93a386Sopenharmony_ci    GrUniqueKey key;
135cb93a386Sopenharmony_ci    if (proxy->getUniqueKey().isValid()) {
136cb93a386Sopenharmony_ci        key = proxy->getUniqueKey();
137cb93a386Sopenharmony_ci    } else {
138cb93a386Sopenharmony_ci        GrMakeKeyFromImageID(&key, id, SkIRect::MakeWH(64, 64));
139cb93a386Sopenharmony_ci        ++id;
140cb93a386Sopenharmony_ci
141cb93a386Sopenharmony_ci        // Assigning the uniqueKey adds the proxy to the hash but doesn't force instantiation
142cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, !proxyProvider->numUniqueKeyProxies_TestOnly());
143cb93a386Sopenharmony_ci        SkAssertResult(proxyProvider->assignUniqueKeyToProxy(key, proxy.get()));
144cb93a386Sopenharmony_ci    }
145cb93a386Sopenharmony_ci
146cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 1 == proxyProvider->numUniqueKeyProxies_TestOnly());
147cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, startCacheCount == cache->getResourceCount());
148cb93a386Sopenharmony_ci
149cb93a386Sopenharmony_ci    // setUniqueKey had better stick
150cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, key == proxy->getUniqueKey());
151cb93a386Sopenharmony_ci
152cb93a386Sopenharmony_ci    // We just added it, surely we can find it
153cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, proxyProvider->findOrCreateProxyByUniqueKey(key));
154cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 1 == proxyProvider->numUniqueKeyProxies_TestOnly());
155cb93a386Sopenharmony_ci
156cb93a386Sopenharmony_ci    int expectedCacheCount = startCacheCount + (proxy->isInstantiated() ? 0 : cacheEntriesPerProxy);
157cb93a386Sopenharmony_ci
158cb93a386Sopenharmony_ci    // Once instantiated, the backing resource should have the same key
159cb93a386Sopenharmony_ci    SkAssertResult(proxy->instantiate(resourceProvider));
160cb93a386Sopenharmony_ci    const GrUniqueKey texKey = proxy->peekSurface()->getUniqueKey();
161cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, texKey.isValid());
162cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, key == texKey);
163cb93a386Sopenharmony_ci
164cb93a386Sopenharmony_ci    // An Unbudgeted-cacheable resource will not get purged when a proxy with the same key is
165cb93a386Sopenharmony_ci    // deleted.
166cb93a386Sopenharmony_ci    bool expectResourceToOutliveProxy = proxy->peekSurface()->resourcePriv().budgetedType() ==
167cb93a386Sopenharmony_ci                                        GrBudgetedType::kUnbudgetedCacheable;
168cb93a386Sopenharmony_ci
169cb93a386Sopenharmony_ci    // An Unbudgeted-uncacheable resource is never kept alive if it's ref cnt reaches zero even if
170cb93a386Sopenharmony_ci    // it has a key.
171cb93a386Sopenharmony_ci    bool expectDeletingProxyToDeleteResource =
172cb93a386Sopenharmony_ci            proxy->peekSurface()->resourcePriv().budgetedType() ==
173cb93a386Sopenharmony_ci            GrBudgetedType::kUnbudgetedUncacheable;
174cb93a386Sopenharmony_ci
175cb93a386Sopenharmony_ci    // deleting the proxy should delete it from the hash but not the cache
176cb93a386Sopenharmony_ci    proxy = nullptr;
177cb93a386Sopenharmony_ci    if (expectDeletingProxyToDeleteResource) {
178cb93a386Sopenharmony_ci        expectedCacheCount -= cacheEntriesPerProxy;
179cb93a386Sopenharmony_ci    }
180cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 0 == proxyProvider->numUniqueKeyProxies_TestOnly());
181cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, expectedCacheCount == cache->getResourceCount());
182cb93a386Sopenharmony_ci
183cb93a386Sopenharmony_ci    // If the proxy was cached refinding it should bring it back to life
184cb93a386Sopenharmony_ci    proxy = proxyProvider->findOrCreateProxyByUniqueKey(key);
185cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, proxy);
186cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 1 == proxyProvider->numUniqueKeyProxies_TestOnly());
187cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, expectedCacheCount == cache->getResourceCount());
188cb93a386Sopenharmony_ci
189cb93a386Sopenharmony_ci    // Mega-purging it should remove it from both the hash and the cache
190cb93a386Sopenharmony_ci    proxy = nullptr;
191cb93a386Sopenharmony_ci    cache->purgeUnlockedResources();
192cb93a386Sopenharmony_ci    if (!expectResourceToOutliveProxy) {
193cb93a386Sopenharmony_ci        expectedCacheCount -= cacheEntriesPerProxy;
194cb93a386Sopenharmony_ci    }
195cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, expectedCacheCount == cache->getResourceCount());
196cb93a386Sopenharmony_ci
197cb93a386Sopenharmony_ci    // If the texture was deleted then the proxy should no longer be findable. Otherwise, it should
198cb93a386Sopenharmony_ci    // be.
199cb93a386Sopenharmony_ci    proxy = proxyProvider->findOrCreateProxyByUniqueKey(key);
200cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, expectResourceToOutliveProxy ? (bool)proxy : !proxy);
201cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, expectedCacheCount == cache->getResourceCount());
202cb93a386Sopenharmony_ci
203cb93a386Sopenharmony_ci    if (expectResourceToOutliveProxy) {
204cb93a386Sopenharmony_ci        proxy.reset();
205cb93a386Sopenharmony_ci        GrUniqueKeyInvalidatedMessage msg(texKey, dContext->priv().contextID());
206cb93a386Sopenharmony_ci        SkMessageBus<GrUniqueKeyInvalidatedMessage, uint32_t>::Post(msg);
207cb93a386Sopenharmony_ci        cache->purgeAsNeeded();
208cb93a386Sopenharmony_ci        expectedCacheCount -= cacheEntriesPerProxy;
209cb93a386Sopenharmony_ci        proxy = proxyProvider->findOrCreateProxyByUniqueKey(key);
210cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, !proxy);
211cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, expectedCacheCount == cache->getResourceCount());
212cb93a386Sopenharmony_ci    }
213cb93a386Sopenharmony_ci}
214cb93a386Sopenharmony_ci
215cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////////////////////////
216cb93a386Sopenharmony_ci// Invalidation test
217cb93a386Sopenharmony_ci
218cb93a386Sopenharmony_ci// Test if invalidating unique ids operates as expected for texture proxies.
219cb93a386Sopenharmony_cistatic void invalidation_test(GrDirectContext* dContext,
220cb93a386Sopenharmony_ci                              skiatest::Reporter* reporter,
221cb93a386Sopenharmony_ci                              int cacheEntriesPerProxy) {
222cb93a386Sopenharmony_ci
223cb93a386Sopenharmony_ci    GrProxyProvider* proxyProvider = dContext->priv().proxyProvider();
224cb93a386Sopenharmony_ci    GrResourceCache* cache = dContext->priv().getResourceCache();
225cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
226cb93a386Sopenharmony_ci
227cb93a386Sopenharmony_ci    sk_sp<SkImage> rasterImg;
228cb93a386Sopenharmony_ci
229cb93a386Sopenharmony_ci    {
230cb93a386Sopenharmony_ci        SkImageInfo ii = SkImageInfo::Make(64, 64, kRGBA_8888_SkColorType, kOpaque_SkAlphaType);
231cb93a386Sopenharmony_ci
232cb93a386Sopenharmony_ci        SkBitmap bm;
233cb93a386Sopenharmony_ci        bm.allocPixels(ii);
234cb93a386Sopenharmony_ci
235cb93a386Sopenharmony_ci        rasterImg = bm.asImage();
236cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, 0 == proxyProvider->numUniqueKeyProxies_TestOnly());
237cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
238cb93a386Sopenharmony_ci    }
239cb93a386Sopenharmony_ci
240cb93a386Sopenharmony_ci    // Some of our backends use buffers to do uploads that will live in our resource cache. So we
241cb93a386Sopenharmony_ci    // need to account for those extra resources here.
242cb93a386Sopenharmony_ci    int bufferResources = 0;
243cb93a386Sopenharmony_ci    if (dContext->backend() == GrBackendApi::kDawn ||
244cb93a386Sopenharmony_ci        dContext->backend() == GrBackendApi::kVulkan ||
245cb93a386Sopenharmony_ci        dContext->backend() == GrBackendApi::kDirect3D ||
246cb93a386Sopenharmony_ci        dContext->backend() == GrBackendApi::kMetal) {
247cb93a386Sopenharmony_ci        bufferResources = 1;
248cb93a386Sopenharmony_ci    }
249cb93a386Sopenharmony_ci
250cb93a386Sopenharmony_ci    sk_sp<SkImage> textureImg = rasterImg->makeTextureImage(dContext);
251cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 0 == proxyProvider->numUniqueKeyProxies_TestOnly());
252cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, cacheEntriesPerProxy + bufferResources == cache->getResourceCount());
253cb93a386Sopenharmony_ci
254cb93a386Sopenharmony_ci    rasterImg = nullptr;        // this invalidates the uniqueKey
255cb93a386Sopenharmony_ci
256cb93a386Sopenharmony_ci    // this forces the cache to respond to the inval msg
257cb93a386Sopenharmony_ci    size_t maxBytes = dContext->getResourceCacheLimit();
258cb93a386Sopenharmony_ci    dContext->setResourceCacheLimit(maxBytes-1);
259cb93a386Sopenharmony_ci
260cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 0 == proxyProvider->numUniqueKeyProxies_TestOnly());
261cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, cacheEntriesPerProxy + bufferResources == cache->getResourceCount());
262cb93a386Sopenharmony_ci
263cb93a386Sopenharmony_ci    textureImg = nullptr;
264cb93a386Sopenharmony_ci
265cb93a386Sopenharmony_ci    // For backends that use buffers to upload lets make sure that work has been submit and done
266cb93a386Sopenharmony_ci    // before we try to purge all resources.
267cb93a386Sopenharmony_ci    dContext->submit(true);
268cb93a386Sopenharmony_ci
269cb93a386Sopenharmony_ci#ifdef SK_DAWN
270cb93a386Sopenharmony_ci    // The forced cpu sync in dawn doesn't actually mean the async map will finish thus we may
271cb93a386Sopenharmony_ci    // still have a ref on the GrGpuBuffer and it will not get purged by the call below. We dig
272cb93a386Sopenharmony_ci    // deep into the dawn gpu to make sure we wait for the async map to finish.
273cb93a386Sopenharmony_ci    if (dContext->backend() == GrBackendApi::kDawn) {
274cb93a386Sopenharmony_ci        GrDawnGpu* gpu = static_cast<GrDawnGpu*>(dContext->priv().getGpu());
275cb93a386Sopenharmony_ci        gpu->waitOnAllBusyStagingBuffers();
276cb93a386Sopenharmony_ci    }
277cb93a386Sopenharmony_ci#endif
278cb93a386Sopenharmony_ci
279cb93a386Sopenharmony_ci    dContext->priv().getResourceCache()->purgeUnlockedResources();
280cb93a386Sopenharmony_ci
281cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 0 == proxyProvider->numUniqueKeyProxies_TestOnly());
282cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
283cb93a386Sopenharmony_ci}
284cb93a386Sopenharmony_ci
285cb93a386Sopenharmony_ci// Test if invalidating unique ids prior to instantiating operates as expected
286cb93a386Sopenharmony_cistatic void invalidation_and_instantiation_test(GrDirectContext* dContext,
287cb93a386Sopenharmony_ci                                                skiatest::Reporter* reporter,
288cb93a386Sopenharmony_ci                                                int cacheEntriesPerProxy) {
289cb93a386Sopenharmony_ci    GrProxyProvider* proxyProvider = dContext->priv().proxyProvider();
290cb93a386Sopenharmony_ci    GrResourceProvider* resourceProvider = dContext->priv().resourceProvider();
291cb93a386Sopenharmony_ci    GrResourceCache* cache = dContext->priv().getResourceCache();
292cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
293cb93a386Sopenharmony_ci
294cb93a386Sopenharmony_ci    static GrUniqueKey::Domain d = GrUniqueKey::GenerateDomain();
295cb93a386Sopenharmony_ci    GrUniqueKey key;
296cb93a386Sopenharmony_ci    GrUniqueKey::Builder builder(&key, d, 1, nullptr);
297cb93a386Sopenharmony_ci    builder[0] = 0;
298cb93a386Sopenharmony_ci    builder.finish();
299cb93a386Sopenharmony_ci
300cb93a386Sopenharmony_ci    // Create proxy, assign unique key
301cb93a386Sopenharmony_ci    sk_sp<GrTextureProxy> proxy = deferred_tex(reporter, dContext, proxyProvider,
302cb93a386Sopenharmony_ci                                               SkBackingFit::kExact);
303cb93a386Sopenharmony_ci    SkAssertResult(proxyProvider->assignUniqueKeyToProxy(key, proxy.get()));
304cb93a386Sopenharmony_ci
305cb93a386Sopenharmony_ci    // Send an invalidation message, which will be sitting in the cache's inbox
306cb93a386Sopenharmony_ci    SkMessageBus<GrUniqueKeyInvalidatedMessage, uint32_t>::Post(
307cb93a386Sopenharmony_ci            GrUniqueKeyInvalidatedMessage(key, dContext->priv().contextID()));
308cb93a386Sopenharmony_ci
309cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 1 == proxyProvider->numUniqueKeyProxies_TestOnly());
310cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
311cb93a386Sopenharmony_ci
312cb93a386Sopenharmony_ci    // Instantiate the proxy. This will trigger the message to be processed, so the resulting
313cb93a386Sopenharmony_ci    // texture should *not* have the unique key on it!
314cb93a386Sopenharmony_ci    SkAssertResult(proxy->instantiate(resourceProvider));
315cb93a386Sopenharmony_ci
316cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, !proxy->getUniqueKey().isValid());
317cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, !proxy->peekTexture()->getUniqueKey().isValid());
318cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 0 == proxyProvider->numUniqueKeyProxies_TestOnly());
319cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, cacheEntriesPerProxy == cache->getResourceCount());
320cb93a386Sopenharmony_ci
321cb93a386Sopenharmony_ci    proxy = nullptr;
322cb93a386Sopenharmony_ci    dContext->priv().getResourceCache()->purgeUnlockedResources();
323cb93a386Sopenharmony_ci
324cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 0 == proxyProvider->numUniqueKeyProxies_TestOnly());
325cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
326cb93a386Sopenharmony_ci}
327cb93a386Sopenharmony_ci
328cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(TextureProxyTest, reporter, ctxInfo) {
329cb93a386Sopenharmony_ci    auto direct = ctxInfo.directContext();
330cb93a386Sopenharmony_ci    GrProxyProvider* proxyProvider = direct->priv().proxyProvider();
331cb93a386Sopenharmony_ci    GrResourceCache* cache = direct->priv().getResourceCache();
332cb93a386Sopenharmony_ci
333cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, !proxyProvider->numUniqueKeyProxies_TestOnly());
334cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
335cb93a386Sopenharmony_ci
336cb93a386Sopenharmony_ci    // As we transition to using attachments instead of GrTextures and GrRenderTargets individual
337cb93a386Sopenharmony_ci    // proxy instansiations may add multiple things to the cache. There would be an entry for the
338cb93a386Sopenharmony_ci    // GrTexture/GrRenderTarget and entries for one or more attachments.
339cb93a386Sopenharmony_ci    int cacheEntriesPerProxy = 1;
340cb93a386Sopenharmony_ci    // We currently only have attachments on the vulkan and metal backends
341cb93a386Sopenharmony_ci    if (direct->backend() == GrBackend::kVulkan || direct->backend() == GrBackend::kMetal) {
342cb93a386Sopenharmony_ci        cacheEntriesPerProxy++;
343cb93a386Sopenharmony_ci        // If we ever have a test with multisamples this would have an additional attachment as
344cb93a386Sopenharmony_ci        // well.
345cb93a386Sopenharmony_ci    }
346cb93a386Sopenharmony_ci
347cb93a386Sopenharmony_ci    for (auto fit : { SkBackingFit::kExact, SkBackingFit::kApprox }) {
348cb93a386Sopenharmony_ci        for (auto create : { deferred_tex, deferred_texRT, wrapped, wrapped_with_key }) {
349cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
350cb93a386Sopenharmony_ci            basic_test(direct, reporter, create(reporter, direct, proxyProvider, fit),
351cb93a386Sopenharmony_ci                       cacheEntriesPerProxy);
352cb93a386Sopenharmony_ci        }
353cb93a386Sopenharmony_ci
354cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
355cb93a386Sopenharmony_ci        cache->purgeUnlockedResources();
356cb93a386Sopenharmony_ci    }
357cb93a386Sopenharmony_ci
358cb93a386Sopenharmony_ci    basic_test(direct, reporter, create_wrapped_backend(direct), cacheEntriesPerProxy);
359cb93a386Sopenharmony_ci
360cb93a386Sopenharmony_ci    invalidation_test(direct, reporter, cacheEntriesPerProxy);
361cb93a386Sopenharmony_ci    invalidation_and_instantiation_test(direct, reporter, cacheEntriesPerProxy);
362cb93a386Sopenharmony_ci}
363