blob: 8862292cec08d5dd05bc549e2ea4ffc1449a2238 [file] [log] [blame]
Robert Phillips5af44de2017-07-18 14:49:38 -04001/*
2 * Copyright 2017 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Robert Phillipse19babf2020-04-06 13:57:30 -04008#include "include/core/SkCanvas.h"
9#include "include/core/SkSurface.h"
Robert Phillips6d344c32020-07-06 10:56:46 -040010#include "include/gpu/GrDirectContext.h"
Adlai Hollera0693042020-10-14 11:23:11 -040011#include "src/gpu/GrDirectContextPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "src/gpu/GrGpu.h"
13#include "src/gpu/GrProxyProvider.h"
14#include "src/gpu/GrResourceAllocator.h"
15#include "src/gpu/GrResourceProvider.h"
16#include "src/gpu/GrSurfaceProxyPriv.h"
Greg Daniel456f9b52020-03-05 19:14:18 +000017#include "src/gpu/GrTexture.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040018#include "src/gpu/GrTextureProxy.h"
Robert Phillipse19babf2020-04-06 13:57:30 -040019#include "tests/Test.h"
Brian Salomon72050802020-10-12 20:45:06 -040020#include "tools/gpu/ManagedBackendTexture.h"
Robert Phillips1734dd32018-08-21 13:52:09 -040021
Robert Phillips57aa3672017-07-21 11:38:13 -040022struct ProxyParams {
23 int fSize;
Brian Salomonf2c2ba92019-07-17 09:59:59 -040024 GrRenderable fRenderable;
Robert Phillipsc80b0e92019-07-23 10:27:09 -040025 GrColorType fColorType;
Robert Phillips57aa3672017-07-21 11:38:13 -040026 SkBackingFit fFit;
27 int fSampleCnt;
Robert Phillipsc476e5d2019-03-26 14:50:08 -040028 SkBudgeted fBudgeted;
Robert Phillips57aa3672017-07-21 11:38:13 -040029 // TODO: do we care about mipmapping
30};
31
Robert Phillips3d4cac52019-06-11 08:08:08 -040032static sk_sp<GrSurfaceProxy> make_deferred(GrProxyProvider* proxyProvider, const GrCaps* caps,
33 const ProxyParams& p) {
Robert Phillips0a15cc62019-07-30 12:49:10 -040034 const GrBackendFormat format = caps->getDefaultBackendFormat(p.fColorType, p.fRenderable);
Brian Salomondf1bd6d2020-03-26 20:37:01 -040035 return proxyProvider->createProxy(format, {p.fSize, p.fSize}, p.fRenderable, p.fSampleCnt,
Brian Salomon7e67dca2020-07-21 09:27:25 -040036 GrMipmapped::kNo, p.fFit, p.fBudgeted, GrProtected::kNo);
Robert Phillips57aa3672017-07-21 11:38:13 -040037}
38
Brian Salomon72050802020-10-12 20:45:06 -040039static sk_sp<GrSurfaceProxy> make_backend(GrDirectContext* dContext, const ProxyParams& p) {
Robert Phillipseffd13f2020-07-20 15:00:36 -040040 GrProxyProvider* proxyProvider = dContext->priv().proxyProvider();
Robert Phillips0bd24dc2018-01-16 08:06:32 -050041
Robert Phillipsc80b0e92019-07-23 10:27:09 -040042 SkColorType skColorType = GrColorTypeToSkColorType(p.fColorType);
43 SkASSERT(SkColorType::kUnknown_SkColorType != skColorType);
44
Brian Salomon72050802020-10-12 20:45:06 -040045 auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(
46 dContext, p.fSize, p.fSize, skColorType, GrMipmapped::kNo, GrRenderable::kNo);
Greg Danielc1ad77c2020-05-06 11:40:03 -040047
Brian Salomon72050802020-10-12 20:45:06 -040048 if (!mbet) {
Robert Phillips646f6372018-09-25 09:31:10 -040049 return nullptr;
50 }
Robert Phillips57aa3672017-07-21 11:38:13 -040051
Brian Salomon72050802020-10-12 20:45:06 -040052 return proxyProvider->wrapBackendTexture(mbet->texture(),
53 kBorrow_GrWrapOwnership,
54 GrWrapCacheable::kNo,
55 kRead_GrIOType,
56 mbet->refCountedCallback());
Robert Phillips57aa3672017-07-21 11:38:13 -040057}
58
Robert Phillips5af44de2017-07-18 14:49:38 -040059// Basic test that two proxies with overlapping intervals and compatible descriptors are
60// assigned different GrSurfaces.
Robert Phillips57aa3672017-07-21 11:38:13 -040061static void overlap_test(skiatest::Reporter* reporter, GrResourceProvider* resourceProvider,
Robert Phillips3d4cac52019-06-11 08:08:08 -040062 sk_sp<GrSurfaceProxy> p1, sk_sp<GrSurfaceProxy> p2,
Brian Salomon2c791fc2019-04-02 11:52:03 -040063 bool expectedResult) {
Brian Salomonbeb7f522019-08-30 16:19:42 -040064 GrResourceAllocator alloc(resourceProvider SkDEBUGCODE(, 1));
Robert Phillips5af44de2017-07-18 14:49:38 -040065
Robert Phillips3d4cac52019-06-11 08:08:08 -040066 alloc.addInterval(p1.get(), 0, 4, GrResourceAllocator::ActualUse::kYes);
Robert Phillipsc476e5d2019-03-26 14:50:08 -040067 alloc.incOps();
Robert Phillips3d4cac52019-06-11 08:08:08 -040068 alloc.addInterval(p2.get(), 1, 2, GrResourceAllocator::ActualUse::kYes);
Robert Phillipsc476e5d2019-03-26 14:50:08 -040069 alloc.incOps();
Greg Danielf41b2bd2019-08-22 16:19:24 -040070 alloc.markEndOfOpsTask(0);
Robert Phillips5af44de2017-07-18 14:49:38 -040071
Robert Phillipsc73666f2019-04-24 08:49:48 -040072 alloc.determineRecyclability();
73
Robert Phillipseafd48a2017-11-16 07:52:08 -050074 int startIndex, stopIndex;
Greg Danielaa3dfbe2018-01-29 10:34:25 -050075 GrResourceAllocator::AssignError error;
Brian Salomon577aa0f2018-11-30 13:32:23 -050076 alloc.assign(&startIndex, &stopIndex, &error);
Greg Danielaa3dfbe2018-01-29 10:34:25 -050077 REPORTER_ASSERT(reporter, GrResourceAllocator::AssignError::kNoError == error);
Robert Phillips5af44de2017-07-18 14:49:38 -040078
Brian Salomonfd98c2c2018-07-31 17:25:29 -040079 REPORTER_ASSERT(reporter, p1->peekSurface());
80 REPORTER_ASSERT(reporter, p2->peekSurface());
Robert Phillips57aa3672017-07-21 11:38:13 -040081 bool doTheBackingStoresMatch = p1->underlyingUniqueID() == p2->underlyingUniqueID();
82 REPORTER_ASSERT(reporter, expectedResult == doTheBackingStoresMatch);
Robert Phillips5af44de2017-07-18 14:49:38 -040083}
84
Robert Phillips57aa3672017-07-21 11:38:13 -040085// Test various cases when two proxies do not have overlapping intervals.
86// This mainly acts as a test of the ResourceAllocator's free pool.
87static void non_overlap_test(skiatest::Reporter* reporter, GrResourceProvider* resourceProvider,
Robert Phillips3d4cac52019-06-11 08:08:08 -040088 sk_sp<GrSurfaceProxy> p1, sk_sp<GrSurfaceProxy> p2,
Robert Phillips57aa3672017-07-21 11:38:13 -040089 bool expectedResult) {
Brian Salomonbeb7f522019-08-30 16:19:42 -040090 GrResourceAllocator alloc(resourceProvider SkDEBUGCODE(, 1));
Robert Phillipsc476e5d2019-03-26 14:50:08 -040091
92 alloc.incOps();
93 alloc.incOps();
94 alloc.incOps();
95 alloc.incOps();
96 alloc.incOps();
97 alloc.incOps();
Robert Phillips57aa3672017-07-21 11:38:13 -040098
Robert Phillips3d4cac52019-06-11 08:08:08 -040099 alloc.addInterval(p1.get(), 0, 2, GrResourceAllocator::ActualUse::kYes);
100 alloc.addInterval(p2.get(), 3, 5, GrResourceAllocator::ActualUse::kYes);
Greg Danielf41b2bd2019-08-22 16:19:24 -0400101 alloc.markEndOfOpsTask(0);
Robert Phillips57aa3672017-07-21 11:38:13 -0400102
Robert Phillipsc73666f2019-04-24 08:49:48 -0400103 alloc.determineRecyclability();
104
Robert Phillipseafd48a2017-11-16 07:52:08 -0500105 int startIndex, stopIndex;
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500106 GrResourceAllocator::AssignError error;
Brian Salomon577aa0f2018-11-30 13:32:23 -0500107 alloc.assign(&startIndex, &stopIndex, &error);
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500108 REPORTER_ASSERT(reporter, GrResourceAllocator::AssignError::kNoError == error);
Robert Phillips57aa3672017-07-21 11:38:13 -0400109
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400110 REPORTER_ASSERT(reporter, p1->peekSurface());
111 REPORTER_ASSERT(reporter, p2->peekSurface());
Robert Phillips57aa3672017-07-21 11:38:13 -0400112 bool doTheBackingStoresMatch = p1->underlyingUniqueID() == p2->underlyingUniqueID();
113 REPORTER_ASSERT(reporter, expectedResult == doTheBackingStoresMatch);
114}
115
116DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ResourceAllocatorTest, reporter, ctxInfo) {
Robert Phillips6d344c32020-07-06 10:56:46 -0400117 auto direct = ctxInfo.directContext();
118 const GrCaps* caps = direct->priv().caps();
119 GrProxyProvider* proxyProvider = direct->priv().proxyProvider();
120 GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
Robert Phillips5af44de2017-07-18 14:49:38 -0400121
Robert Phillips57aa3672017-07-21 11:38:13 -0400122 struct TestCase {
123 ProxyParams fP1;
124 ProxyParams fP2;
125 bool fExpectation;
126 };
127
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400128 constexpr GrRenderable kRT = GrRenderable::kYes;
129 constexpr GrRenderable kNotRT = GrRenderable::kNo;
Robert Phillips57aa3672017-07-21 11:38:13 -0400130
131 constexpr bool kShare = true;
132 constexpr bool kDontShare = false;
133 // Non-RT GrSurfaces are never recycled on some platforms.
134 bool kConditionallyShare = resourceProvider->caps()->reuseScratchTextures();
135
Robert Phillipsc80b0e92019-07-23 10:27:09 -0400136 const GrColorType kRGBA = GrColorType::kRGBA_8888;
Greg Danield51fa2f2020-01-22 16:53:38 -0500137 const GrColorType kAlpha = GrColorType::kAlpha_8;
Robert Phillips57aa3672017-07-21 11:38:13 -0400138
139 const SkBackingFit kE = SkBackingFit::kExact;
140 const SkBackingFit kA = SkBackingFit::kApprox;
141
Robert Phillipsc476e5d2019-03-26 14:50:08 -0400142 const SkBudgeted kNotB = SkBudgeted::kNo;
143
Robert Phillips57aa3672017-07-21 11:38:13 -0400144 //--------------------------------------------------------------------------------------------
145 TestCase gOverlappingTests[] = {
Greg Daniel3a365112020-02-14 10:47:18 -0500146 //----------------------------------------------------------------------------------------
147 // Two proxies with overlapping intervals and compatible descriptors should never share
148 // RT version
149 {{64, kRT, kRGBA, kA, 1, kNotB}, {64, kRT, kRGBA, kA, 1, kNotB}, kDontShare},
150 // non-RT version
151 {{64, kNotRT, kRGBA, kA, 1, kNotB}, {64, kNotRT, kRGBA, kA, 1, kNotB}, kDontShare},
Robert Phillips57aa3672017-07-21 11:38:13 -0400152 };
153
154 for (auto test : gOverlappingTests) {
Robert Phillips3d4cac52019-06-11 08:08:08 -0400155 sk_sp<GrSurfaceProxy> p1 = make_deferred(proxyProvider, caps, test.fP1);
156 sk_sp<GrSurfaceProxy> p2 = make_deferred(proxyProvider, caps, test.fP2);
Robert Phillipse5f73282019-06-18 17:15:04 -0400157 overlap_test(reporter, resourceProvider, std::move(p1), std::move(p2), test.fExpectation);
Robert Phillips57aa3672017-07-21 11:38:13 -0400158 }
159
Greg Daniel6fa62e22019-08-07 15:52:37 -0400160 auto beFormat = caps->getDefaultBackendFormat(GrColorType::kRGBA_8888, GrRenderable::kYes);
Robert Phillips6d344c32020-07-06 10:56:46 -0400161 int k2 = direct->priv().caps()->getRenderTargetSampleCount(2, beFormat);
162 int k4 = direct->priv().caps()->getRenderTargetSampleCount(4, beFormat);
Robert Phillips57aa3672017-07-21 11:38:13 -0400163
164 //--------------------------------------------------------------------------------------------
165 TestCase gNonOverlappingTests[] = {
Greg Daniel3a365112020-02-14 10:47:18 -0500166 //----------------------------------------------------------------------------------------
167 // Two non-overlapping intervals w/ compatible proxies should share
168 // both same size & approx
169 {{64, kRT, kRGBA, kA, 1, kNotB}, {64, kRT, kRGBA, kA, 1, kNotB}, kShare},
170 {{64, kNotRT, kRGBA, kA, 1, kNotB},
171 {64, kNotRT, kRGBA, kA, 1, kNotB},
172 kConditionallyShare},
173 // diffs sizes but still approx
174 {{64, kRT, kRGBA, kA, 1, kNotB}, {50, kRT, kRGBA, kA, 1, kNotB}, kShare},
175 {{64, kNotRT, kRGBA, kA, 1, kNotB},
176 {50, kNotRT, kRGBA, kA, 1, kNotB},
177 kConditionallyShare},
178 // sames sizes but exact
179 {{64, kRT, kRGBA, kE, 1, kNotB}, {64, kRT, kRGBA, kE, 1, kNotB}, kShare},
180 {{64, kNotRT, kRGBA, kE, 1, kNotB},
181 {64, kNotRT, kRGBA, kE, 1, kNotB},
182 kConditionallyShare},
183 //----------------------------------------------------------------------------------------
184 // Two non-overlapping intervals w/ different exact sizes should not share
185 {{56, kRT, kRGBA, kE, 1, kNotB}, {54, kRT, kRGBA, kE, 1, kNotB}, kDontShare},
186 // Two non-overlapping intervals w/ _very different_ approx sizes should not share
187 {{255, kRT, kRGBA, kA, 1, kNotB}, {127, kRT, kRGBA, kA, 1, kNotB}, kDontShare},
188 // Two non-overlapping intervals w/ different MSAA sample counts should not share
189 {{64, kRT, kRGBA, kA, k2, kNotB}, {64, kRT, kRGBA, kA, k4, kNotB}, k2 == k4},
190 // Two non-overlapping intervals w/ different configs should not share
191 {{64, kRT, kRGBA, kA, 1, kNotB}, {64, kRT, kAlpha, kA, 1, kNotB}, kDontShare},
192 // Two non-overlapping intervals w/ different RT classifications should never share
193 {{64, kRT, kRGBA, kA, 1, kNotB}, {64, kNotRT, kRGBA, kA, 1, kNotB}, kDontShare},
194 {{64, kNotRT, kRGBA, kA, 1, kNotB}, {64, kRT, kRGBA, kA, 1, kNotB}, kDontShare},
195 // Two non-overlapping intervals w/ different origins should share
196 {{64, kRT, kRGBA, kA, 1, kNotB}, {64, kRT, kRGBA, kA, 1, kNotB}, kShare},
Robert Phillips57aa3672017-07-21 11:38:13 -0400197 };
198
199 for (auto test : gNonOverlappingTests) {
Robert Phillips3d4cac52019-06-11 08:08:08 -0400200 sk_sp<GrSurfaceProxy> p1 = make_deferred(proxyProvider, caps, test.fP1);
201 sk_sp<GrSurfaceProxy> p2 = make_deferred(proxyProvider, caps, test.fP2);
Robert Phillips715d08c2018-07-18 13:56:48 -0400202
Robert Phillips57aa3672017-07-21 11:38:13 -0400203 if (!p1 || !p2) {
204 continue; // creation can fail (i.e., for msaa4 on iOS)
205 }
Robert Phillips715d08c2018-07-18 13:56:48 -0400206
Robert Phillipse5f73282019-06-18 17:15:04 -0400207 non_overlap_test(reporter, resourceProvider, std::move(p1), std::move(p2),
208 test.fExpectation);
Robert Phillips57aa3672017-07-21 11:38:13 -0400209 }
210
211 {
212 // Wrapped backend textures should never be reused
213 TestCase t[1] = {
Greg Daniel3a365112020-02-14 10:47:18 -0500214 {{64, kNotRT, kRGBA, kE, 1, kNotB}, {64, kNotRT, kRGBA, kE, 1, kNotB}, kDontShare}};
Robert Phillips57aa3672017-07-21 11:38:13 -0400215
Brian Salomon72050802020-10-12 20:45:06 -0400216 sk_sp<GrSurfaceProxy> p1 = make_backend(direct, t[0].fP1);
Robert Phillips3d4cac52019-06-11 08:08:08 -0400217 sk_sp<GrSurfaceProxy> p2 = make_deferred(proxyProvider, caps, t[0].fP2);
Robert Phillips715d08c2018-07-18 13:56:48 -0400218
Robert Phillipse5f73282019-06-18 17:15:04 -0400219 non_overlap_test(reporter, resourceProvider, std::move(p1), std::move(p2),
220 t[0].fExpectation);
Robert Phillips57aa3672017-07-21 11:38:13 -0400221 }
Robert Phillips5af44de2017-07-18 14:49:38 -0400222}
Robert Phillips1734dd32018-08-21 13:52:09 -0400223
Robert Phillipseffd13f2020-07-20 15:00:36 -0400224static void draw(GrRecordingContext* rContext) {
Robert Phillips1734dd32018-08-21 13:52:09 -0400225 SkImageInfo ii = SkImageInfo::Make(1024, 1024, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
226
Robert Phillipseffd13f2020-07-20 15:00:36 -0400227 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(rContext, SkBudgeted::kYes,
Robert Phillips1734dd32018-08-21 13:52:09 -0400228 ii, 1, kTopLeft_GrSurfaceOrigin, nullptr);
229
230 SkCanvas* c = s->getCanvas();
231
232 c->clear(SK_ColorBLACK);
233}
234
235
236DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ResourceAllocatorStressTest, reporter, ctxInfo) {
Robert Phillips6d344c32020-07-06 10:56:46 -0400237 auto context = ctxInfo.directContext();
Robert Phillips1734dd32018-08-21 13:52:09 -0400238
Robert Phillipscf39f372019-09-03 10:29:20 -0400239 size_t maxBytes = context->getResourceCacheLimit();
Robert Phillips1734dd32018-08-21 13:52:09 -0400240
Robert Phillipscf39f372019-09-03 10:29:20 -0400241 context->setResourceCacheLimit(0); // We'll always be overbudget
Robert Phillips1734dd32018-08-21 13:52:09 -0400242
243 draw(context);
244 draw(context);
245 draw(context);
246 draw(context);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400247 context->flushAndSubmit();
Robert Phillips1734dd32018-08-21 13:52:09 -0400248
Robert Phillipscf39f372019-09-03 10:29:20 -0400249 context->setResourceCacheLimit(maxBytes);
Robert Phillips1734dd32018-08-21 13:52:09 -0400250}
Brian Salomon577aa0f2018-11-30 13:32:23 -0500251
Greg Danielf41b2bd2019-08-22 16:19:24 -0400252// Set up so there are two opsTasks that need to be flushed but the resource allocator thinks
253// it is over budget. The two opsTasks should be flushed separately and the opsTask indices
Robert Phillipsc476e5d2019-03-26 14:50:08 -0400254// returned from assign should be correct.
255DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ResourceAllocatorOverBudgetTest, reporter, ctxInfo) {
Robert Phillips6d344c32020-07-06 10:56:46 -0400256 auto context = ctxInfo.directContext();
Robert Phillipsc476e5d2019-03-26 14:50:08 -0400257 const GrCaps* caps = context->priv().caps();
258 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
259 GrResourceProvider* resourceProvider = context->priv().resourceProvider();
260
Robert Phillipscf39f372019-09-03 10:29:20 -0400261 size_t origMaxBytes = context->getResourceCacheLimit();
Robert Phillipsc476e5d2019-03-26 14:50:08 -0400262
263 // Force the resource allocator to always believe it is over budget
Robert Phillipscf39f372019-09-03 10:29:20 -0400264 context->setResourceCacheLimit(0);
Robert Phillipsc476e5d2019-03-26 14:50:08 -0400265
Greg Daniel3a365112020-02-14 10:47:18 -0500266 const ProxyParams params = {
267 64, GrRenderable::kNo, GrColorType::kRGBA_8888, SkBackingFit::kExact,
268 1, SkBudgeted::kYes};
Robert Phillipsc476e5d2019-03-26 14:50:08 -0400269
270 {
Robert Phillips3d4cac52019-06-11 08:08:08 -0400271 sk_sp<GrSurfaceProxy> p1 = make_deferred(proxyProvider, caps, params);
272 sk_sp<GrSurfaceProxy> p2 = make_deferred(proxyProvider, caps, params);
273 sk_sp<GrSurfaceProxy> p3 = make_deferred(proxyProvider, caps, params);
274 sk_sp<GrSurfaceProxy> p4 = make_deferred(proxyProvider, caps, params);
Robert Phillipsc476e5d2019-03-26 14:50:08 -0400275
Brian Salomonbeb7f522019-08-30 16:19:42 -0400276 GrResourceAllocator alloc(resourceProvider SkDEBUGCODE(, 2));
Robert Phillipsc476e5d2019-03-26 14:50:08 -0400277
Robert Phillips3d4cac52019-06-11 08:08:08 -0400278 alloc.addInterval(p1.get(), 0, 0, GrResourceAllocator::ActualUse::kYes);
Robert Phillipsc476e5d2019-03-26 14:50:08 -0400279 alloc.incOps();
Robert Phillips3d4cac52019-06-11 08:08:08 -0400280 alloc.addInterval(p2.get(), 1, 1, GrResourceAllocator::ActualUse::kYes);
Robert Phillipsc476e5d2019-03-26 14:50:08 -0400281 alloc.incOps();
Greg Danielf41b2bd2019-08-22 16:19:24 -0400282 alloc.markEndOfOpsTask(0);
Robert Phillipsc476e5d2019-03-26 14:50:08 -0400283
Robert Phillips3d4cac52019-06-11 08:08:08 -0400284 alloc.addInterval(p3.get(), 2, 2, GrResourceAllocator::ActualUse::kYes);
Robert Phillipsc476e5d2019-03-26 14:50:08 -0400285 alloc.incOps();
Robert Phillips3d4cac52019-06-11 08:08:08 -0400286 alloc.addInterval(p4.get(), 3, 3, GrResourceAllocator::ActualUse::kYes);
Robert Phillipsc476e5d2019-03-26 14:50:08 -0400287 alloc.incOps();
Greg Danielf41b2bd2019-08-22 16:19:24 -0400288 alloc.markEndOfOpsTask(1);
Robert Phillipsc476e5d2019-03-26 14:50:08 -0400289
290 int startIndex, stopIndex;
291 GrResourceAllocator::AssignError error;
292
Robert Phillipsc73666f2019-04-24 08:49:48 -0400293 alloc.determineRecyclability();
294
Robert Phillipsc476e5d2019-03-26 14:50:08 -0400295 alloc.assign(&startIndex, &stopIndex, &error);
296 REPORTER_ASSERT(reporter, GrResourceAllocator::AssignError::kNoError == error);
297 REPORTER_ASSERT(reporter, 0 == startIndex && 1 == stopIndex);
298
299 alloc.assign(&startIndex, &stopIndex, &error);
300 REPORTER_ASSERT(reporter, GrResourceAllocator::AssignError::kNoError == error);
301 REPORTER_ASSERT(reporter, 1 == startIndex && 2 == stopIndex);
Robert Phillipsc476e5d2019-03-26 14:50:08 -0400302 }
303
Robert Phillipscf39f372019-09-03 10:29:20 -0400304 context->setResourceCacheLimit(origMaxBytes);
Robert Phillipsc476e5d2019-03-26 14:50:08 -0400305}
Greg Danield72dd4d2019-08-29 14:37:46 -0400306
307// This test is used to make sure we are tracking the current task index during the assign call in
308// the GrResourceAllocator. Specifically we can fall behind if we have intervals that don't
309// use the allocator. In this case we need to possibly increment the fCurOpsTaskIndex multiple times
310// to get in back in sync. We had a bug where we'd only every increment the index by one,
311// http://crbug.com/996610.
312DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ResourceAllocatorCurOpsTaskIndexTest,
313 reporter, ctxInfo) {
Robert Phillips6d344c32020-07-06 10:56:46 -0400314 auto context = ctxInfo.directContext();
Greg Danield72dd4d2019-08-29 14:37:46 -0400315 const GrCaps* caps = context->priv().caps();
316 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
317 GrResourceProvider* resourceProvider = context->priv().resourceProvider();
318
Robert Phillipscf39f372019-09-03 10:29:20 -0400319 size_t origMaxBytes = context->getResourceCacheLimit();
Greg Danield72dd4d2019-08-29 14:37:46 -0400320
321 // Force the resource allocator to always believe it is over budget
Robert Phillipscf39f372019-09-03 10:29:20 -0400322 context->setResourceCacheLimit(0);
Greg Danield72dd4d2019-08-29 14:37:46 -0400323
324 ProxyParams params;
325 params.fFit = SkBackingFit::kExact;
Greg Danield72dd4d2019-08-29 14:37:46 -0400326 params.fColorType = GrColorType::kRGBA_8888;
327 params.fRenderable = GrRenderable::kYes;
328 params.fSampleCnt = 1;
329 params.fSize = 100;
330 params.fBudgeted = SkBudgeted::kYes;
331
332 sk_sp<GrSurfaceProxy> proxy1 = make_deferred(proxyProvider, caps, params);
333 if (!proxy1) {
334 return;
335 }
336 sk_sp<GrSurfaceProxy> proxy2 = make_deferred(proxyProvider, caps, params);
337 if (!proxy2) {
338 return;
339 }
340
341 // Wrapped proxy that will be ignored by the resourceAllocator. We use this to try and get the
342 // resource allocator fCurOpsTaskIndex to fall behind what it really should be.
Brian Salomon72050802020-10-12 20:45:06 -0400343 sk_sp<GrSurfaceProxy> proxyWrapped = make_backend(context, params);
Greg Danield72dd4d2019-08-29 14:37:46 -0400344 if (!proxyWrapped) {
345 return;
346 }
Greg Danield72dd4d2019-08-29 14:37:46 -0400347
348 // Same as above, but we actually need to have at least two intervals that don't go through the
349 // resource allocator to expose the index bug.
Brian Salomon72050802020-10-12 20:45:06 -0400350 sk_sp<GrSurfaceProxy> proxyWrapped2 = make_backend(context, params);
Greg Danield72dd4d2019-08-29 14:37:46 -0400351 if (!proxyWrapped2) {
Greg Danield72dd4d2019-08-29 14:37:46 -0400352 return;
353 }
Greg Danield72dd4d2019-08-29 14:37:46 -0400354
Brian Salomonbeb7f522019-08-30 16:19:42 -0400355 GrResourceAllocator alloc(resourceProvider SkDEBUGCODE(, 4));
Greg Danield72dd4d2019-08-29 14:37:46 -0400356
357 alloc.addInterval(proxyWrapped.get(), 0, 0, GrResourceAllocator::ActualUse::kYes);
358 alloc.incOps();
359 alloc.markEndOfOpsTask(0);
360
361 alloc.addInterval(proxyWrapped2.get(), 1, 1, GrResourceAllocator::ActualUse::kYes);
362 alloc.incOps();
363 alloc.markEndOfOpsTask(1);
364
365 alloc.addInterval(proxy1.get(), 2, 2, GrResourceAllocator::ActualUse::kYes);
366 alloc.incOps();
367 alloc.markEndOfOpsTask(2);
368
369 // We want to force the resource allocator to do a intermediateFlush for the previous interval.
370 // But if it is the resource allocator is at the of its list of intervals it skips the
371 // intermediate flush call, so we add another interval here so it is not skipped.
372 alloc.addInterval(proxy2.get(), 3, 3, GrResourceAllocator::ActualUse::kYes);
373 alloc.incOps();
374 alloc.markEndOfOpsTask(3);
375
376 int startIndex, stopIndex;
377 GrResourceAllocator::AssignError error;
378
379 alloc.determineRecyclability();
380
381 alloc.assign(&startIndex, &stopIndex, &error);
382 REPORTER_ASSERT(reporter, GrResourceAllocator::AssignError::kNoError == error);
383 // The original bug in the allocator here would return a stopIndex of 2 since it would have only
384 // incremented its fCurOpsTaskIndex once instead of the needed two times to skip the first two
385 // unused intervals.
386 REPORTER_ASSERT(reporter, 0 == startIndex && 3 == stopIndex);
387
388 alloc.assign(&startIndex, &stopIndex, &error);
389 REPORTER_ASSERT(reporter, GrResourceAllocator::AssignError::kNoError == error);
390 REPORTER_ASSERT(reporter, 3 == startIndex && 4 == stopIndex);
391
Robert Phillipscf39f372019-09-03 10:29:20 -0400392 context->setResourceCacheLimit(origMaxBytes);
Greg Danield72dd4d2019-08-29 14:37:46 -0400393}
394