blob: e839d0452f7d2601d6122ee03d402f25fe532373 [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 Phillips5af44de2017-07-18 14:49:38 -04008#include "SkTypes.h"
9
Robert Phillips5af44de2017-07-18 14:49:38 -040010#include "Test.h"
11
Robert Phillips57aa3672017-07-21 11:38:13 -040012#include "GrContextPriv.h"
13#include "GrGpu.h"
Robert Phillips0bd24dc2018-01-16 08:06:32 -050014#include "GrProxyProvider.h"
Robert Phillips5af44de2017-07-18 14:49:38 -040015#include "GrResourceAllocator.h"
Robert Phillips57aa3672017-07-21 11:38:13 -040016#include "GrResourceProvider.h"
Robert Phillips5af44de2017-07-18 14:49:38 -040017#include "GrSurfaceProxyPriv.h"
Robert Phillips57aa3672017-07-21 11:38:13 -040018#include "GrTexture.h"
Robert Phillips5af44de2017-07-18 14:49:38 -040019#include "GrTextureProxy.h"
Greg Daniel4684f822018-03-08 15:27:36 -050020#include "GrUninstantiateProxyTracker.h"
Robert Phillips5af44de2017-07-18 14:49:38 -040021
Robert Phillips1734dd32018-08-21 13:52:09 -040022#include "SkSurface.h"
23
Robert Phillips57aa3672017-07-21 11:38:13 -040024struct ProxyParams {
25 int fSize;
26 bool fIsRT;
Robert Phillips646f6372018-09-25 09:31:10 -040027 SkColorType fColorType;
Robert Phillips57aa3672017-07-21 11:38:13 -040028 SkBackingFit fFit;
29 int fSampleCnt;
30 GrSurfaceOrigin fOrigin;
31 // TODO: do we care about mipmapping
32};
33
Robert Phillips715d08c2018-07-18 13:56:48 -040034static GrSurfaceProxy* make_deferred(GrProxyProvider* proxyProvider, const ProxyParams& p) {
Robert Phillips646f6372018-09-25 09:31:10 -040035 GrColorType grCT = SkColorTypeToGrColorType(p.fColorType);
36 GrPixelConfig config = GrColorTypeToPixelConfig(grCT, GrSRGBEncoded::kNo);
37
Robert Phillips57aa3672017-07-21 11:38:13 -040038 GrSurfaceDesc desc;
39 desc.fFlags = p.fIsRT ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags;
Robert Phillips57aa3672017-07-21 11:38:13 -040040 desc.fWidth = p.fSize;
41 desc.fHeight = p.fSize;
Robert Phillips646f6372018-09-25 09:31:10 -040042 desc.fConfig = config;
Robert Phillips57aa3672017-07-21 11:38:13 -040043 desc.fSampleCnt = p.fSampleCnt;
44
Robert Phillips715d08c2018-07-18 13:56:48 -040045 auto tmp = proxyProvider->createProxy(desc, p.fOrigin, p.fFit, SkBudgeted::kNo);
46 if (!tmp) {
47 return nullptr;
48 }
49 GrSurfaceProxy* ret = tmp.release();
50
51 // Add a read to keep the proxy around but unref it so its backing surfaces can be recycled
52 ret->addPendingRead();
53 ret->unref();
54 return ret;
Robert Phillips57aa3672017-07-21 11:38:13 -040055}
56
Robert Phillips715d08c2018-07-18 13:56:48 -040057static GrSurfaceProxy* make_backend(GrContext* context, const ProxyParams& p,
58 GrBackendTexture* backendTex) {
Robert Phillips0bd24dc2018-01-16 08:06:32 -050059 GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
Robert Phillipsf35fd8d2018-01-22 10:48:15 -050060 GrGpu* gpu = context->contextPriv().getGpu();
Robert Phillips0bd24dc2018-01-16 08:06:32 -050061
Robert Phillipsf35fd8d2018-01-22 10:48:15 -050062 *backendTex = gpu->createTestingOnlyBackendTexture(nullptr, p.fSize, p.fSize,
Robert Phillips646f6372018-09-25 09:31:10 -040063 p.fColorType, false,
Robert Phillipsf35fd8d2018-01-22 10:48:15 -050064 GrMipMapped::kNo);
Robert Phillips646f6372018-09-25 09:31:10 -040065 if (!backendTex->isValid()) {
66 return nullptr;
67 }
Robert Phillips57aa3672017-07-21 11:38:13 -040068
Robert Phillips715d08c2018-07-18 13:56:48 -040069 auto tmp = proxyProvider->wrapBackendTexture(*backendTex, p.fOrigin);
70 if (!tmp) {
71 return nullptr;
72 }
73 GrSurfaceProxy* ret = tmp.release();
74
75 // Add a read to keep the proxy around but unref it so its backing surfaces can be recycled
76 ret->addPendingRead();
77 ret->unref();
78 return ret;
Robert Phillips57aa3672017-07-21 11:38:13 -040079}
80
Brian Salomon26102cb2018-03-09 09:33:19 -050081static void cleanup_backend(GrContext* context, const GrBackendTexture& backendTex) {
Robert Phillipsf35fd8d2018-01-22 10:48:15 -050082 context->contextPriv().getGpu()->deleteTestingOnlyBackendTexture(backendTex);
Robert Phillips57aa3672017-07-21 11:38:13 -040083}
84
Robert Phillips5af44de2017-07-18 14:49:38 -040085// Basic test that two proxies with overlapping intervals and compatible descriptors are
86// assigned different GrSurfaces.
Robert Phillips57aa3672017-07-21 11:38:13 -040087static void overlap_test(skiatest::Reporter* reporter, GrResourceProvider* resourceProvider,
Robert Phillips715d08c2018-07-18 13:56:48 -040088 GrSurfaceProxy* p1, GrSurfaceProxy* p2, bool expectedResult) {
Robert Phillips5af44de2017-07-18 14:49:38 -040089 GrResourceAllocator alloc(resourceProvider);
90
Robert Phillips715d08c2018-07-18 13:56:48 -040091 alloc.addInterval(p1, 0, 4);
92 alloc.addInterval(p2, 1, 2);
Robert Phillipseafd48a2017-11-16 07:52:08 -050093 alloc.markEndOfOpList(0);
Robert Phillips5af44de2017-07-18 14:49:38 -040094
Robert Phillipseafd48a2017-11-16 07:52:08 -050095 int startIndex, stopIndex;
Greg Danielaa3dfbe2018-01-29 10:34:25 -050096 GrResourceAllocator::AssignError error;
Greg Daniel4684f822018-03-08 15:27:36 -050097 GrUninstantiateProxyTracker uninstantiateTracker;
98 alloc.assign(&startIndex, &stopIndex, &uninstantiateTracker, &error);
Greg Danielaa3dfbe2018-01-29 10:34:25 -050099 REPORTER_ASSERT(reporter, GrResourceAllocator::AssignError::kNoError == error);
Robert Phillips5af44de2017-07-18 14:49:38 -0400100
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400101 REPORTER_ASSERT(reporter, p1->peekSurface());
102 REPORTER_ASSERT(reporter, p2->peekSurface());
Robert Phillips57aa3672017-07-21 11:38:13 -0400103 bool doTheBackingStoresMatch = p1->underlyingUniqueID() == p2->underlyingUniqueID();
104 REPORTER_ASSERT(reporter, expectedResult == doTheBackingStoresMatch);
Robert Phillips5af44de2017-07-18 14:49:38 -0400105}
106
Robert Phillips57aa3672017-07-21 11:38:13 -0400107// Test various cases when two proxies do not have overlapping intervals.
108// This mainly acts as a test of the ResourceAllocator's free pool.
109static void non_overlap_test(skiatest::Reporter* reporter, GrResourceProvider* resourceProvider,
Robert Phillips715d08c2018-07-18 13:56:48 -0400110 GrSurfaceProxy* p1, GrSurfaceProxy* p2,
Robert Phillips57aa3672017-07-21 11:38:13 -0400111 bool expectedResult) {
112 GrResourceAllocator alloc(resourceProvider);
113
Robert Phillips715d08c2018-07-18 13:56:48 -0400114 alloc.addInterval(p1, 0, 2);
115 alloc.addInterval(p2, 3, 5);
Robert Phillipseafd48a2017-11-16 07:52:08 -0500116 alloc.markEndOfOpList(0);
Robert Phillips57aa3672017-07-21 11:38:13 -0400117
Robert Phillipseafd48a2017-11-16 07:52:08 -0500118 int startIndex, stopIndex;
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500119 GrResourceAllocator::AssignError error;
Greg Daniel4684f822018-03-08 15:27:36 -0500120 GrUninstantiateProxyTracker uninstantiateTracker;
121 alloc.assign(&startIndex, &stopIndex, &uninstantiateTracker, &error);
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500122 REPORTER_ASSERT(reporter, GrResourceAllocator::AssignError::kNoError == error);
Robert Phillips57aa3672017-07-21 11:38:13 -0400123
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400124 REPORTER_ASSERT(reporter, p1->peekSurface());
125 REPORTER_ASSERT(reporter, p2->peekSurface());
Robert Phillips57aa3672017-07-21 11:38:13 -0400126 bool doTheBackingStoresMatch = p1->underlyingUniqueID() == p2->underlyingUniqueID();
127 REPORTER_ASSERT(reporter, expectedResult == doTheBackingStoresMatch);
128}
129
Robert Phillips4150eea2018-02-07 17:08:21 -0500130bool GrResourceProvider::testingOnly_setExplicitlyAllocateGPUResources(bool newValue) {
131 bool oldValue = fExplicitlyAllocateGPUResources;
132 fExplicitlyAllocateGPUResources = newValue;
133 return oldValue;
134}
135
Robert Phillips57aa3672017-07-21 11:38:13 -0400136DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ResourceAllocatorTest, reporter, ctxInfo) {
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500137 GrProxyProvider* proxyProvider = ctxInfo.grContext()->contextPriv().proxyProvider();
Robert Phillips6be756b2018-01-16 15:07:54 -0500138 GrResourceProvider* resourceProvider = ctxInfo.grContext()->contextPriv().resourceProvider();
Robert Phillips5af44de2017-07-18 14:49:38 -0400139
Robert Phillips4150eea2018-02-07 17:08:21 -0500140 bool orig = resourceProvider->testingOnly_setExplicitlyAllocateGPUResources(true);
141
Robert Phillips57aa3672017-07-21 11:38:13 -0400142 struct TestCase {
143 ProxyParams fP1;
144 ProxyParams fP2;
145 bool fExpectation;
146 };
147
148 constexpr bool kRT = true;
149 constexpr bool kNotRT = false;
150
151 constexpr bool kShare = true;
152 constexpr bool kDontShare = false;
153 // Non-RT GrSurfaces are never recycled on some platforms.
154 bool kConditionallyShare = resourceProvider->caps()->reuseScratchTextures();
155
Robert Phillips646f6372018-09-25 09:31:10 -0400156 const SkColorType kRGBA = kRGBA_8888_SkColorType;
157 const SkColorType kBGRA = kBGRA_8888_SkColorType;
Robert Phillips57aa3672017-07-21 11:38:13 -0400158
159 const SkBackingFit kE = SkBackingFit::kExact;
160 const SkBackingFit kA = SkBackingFit::kApprox;
161
162 const GrSurfaceOrigin kTL = kTopLeft_GrSurfaceOrigin;
163 const GrSurfaceOrigin kBL = kBottomLeft_GrSurfaceOrigin;
164
165 //--------------------------------------------------------------------------------------------
166 TestCase gOverlappingTests[] = {
167 //----------------------------------------------------------------------------------------
168 // Two proxies with overlapping intervals and compatible descriptors should never share
169 // RT version
170 { { 64, kRT, kRGBA, kA, 0, kTL }, { 64, kRT, kRGBA, kA, 0, kTL }, kDontShare },
171 // non-RT version
172 { { 64, kNotRT, kRGBA, kA, 0, kTL }, { 64, kNotRT, kRGBA, kA, 0, kTL }, kDontShare },
173 };
174
175 for (auto test : gOverlappingTests) {
Robert Phillips715d08c2018-07-18 13:56:48 -0400176 GrSurfaceProxy* p1 = make_deferred(proxyProvider, test.fP1);
177 GrSurfaceProxy* p2 = make_deferred(proxyProvider, test.fP2);
178 overlap_test(reporter, resourceProvider, p1, p2, test.fExpectation);
179 p1->completedRead();
180 p2->completedRead();
Robert Phillips57aa3672017-07-21 11:38:13 -0400181 }
182
Robert Phillips646f6372018-09-25 09:31:10 -0400183 int k2 = ctxInfo.grContext()->contextPriv().caps()->getRenderTargetSampleCount(
184 2, kRGBA_8888_GrPixelConfig);
185 int k4 = ctxInfo.grContext()->contextPriv().caps()->getRenderTargetSampleCount(
186 4, kRGBA_8888_GrPixelConfig);
Robert Phillips57aa3672017-07-21 11:38:13 -0400187
188 //--------------------------------------------------------------------------------------------
189 TestCase gNonOverlappingTests[] = {
190 //----------------------------------------------------------------------------------------
191 // Two non-overlapping intervals w/ compatible proxies should share
192 // both same size & approx
193 { { 64, kRT, kRGBA, kA, 0, kTL }, { 64, kRT, kRGBA, kA, 0, kTL }, kShare },
194 { { 64, kNotRT, kRGBA, kA, 0, kTL }, { 64, kNotRT, kRGBA, kA, 0, kTL }, kConditionallyShare },
195 // diffs sizes but still approx
196 { { 64, kRT, kRGBA, kA, 0, kTL }, { 50, kRT, kRGBA, kA, 0, kTL }, kShare },
197 { { 64, kNotRT, kRGBA, kA, 0, kTL }, { 50, kNotRT, kRGBA, kA, 0, kTL }, kConditionallyShare },
198 // sames sizes but exact
199 { { 64, kRT, kRGBA, kE, 0, kTL }, { 64, kRT, kRGBA, kE, 0, kTL }, kShare },
200 { { 64, kNotRT, kRGBA, kE, 0, kTL }, { 64, kNotRT, kRGBA, kE, 0, kTL }, kConditionallyShare },
201 //----------------------------------------------------------------------------------------
202 // Two non-overlapping intervals w/ different exact sizes should not share
203 { { 56, kRT, kRGBA, kE, 0, kTL }, { 54, kRT, kRGBA, kE, 0, kTL }, kDontShare },
204 // Two non-overlapping intervals w/ _very different_ approx sizes should not share
205 { { 255, kRT, kRGBA, kA, 0, kTL }, { 127, kRT, kRGBA, kA, 0, kTL }, kDontShare },
206 // Two non-overlapping intervals w/ different MSAA sample counts should not share
207 { { 64, kRT, kRGBA, kA, k2, kTL },{ 64, kRT, kRGBA, kA, k4, kTL}, k2 == k4 },
208 // Two non-overlapping intervals w/ different configs should not share
209 { { 64, kRT, kRGBA, kA, 0, kTL }, { 64, kRT, kBGRA, kA, 0, kTL }, kDontShare },
210 // Two non-overlapping intervals w/ different RT classifications should never share
211 { { 64, kRT, kRGBA, kA, 0, kTL }, { 64, kNotRT, kRGBA, kA, 0, kTL }, kDontShare },
212 { { 64, kNotRT, kRGBA, kA, 0, kTL }, { 64, kRT, kRGBA, kA, 0, kTL }, kDontShare },
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400213 // Two non-overlapping intervals w/ different origins should share
214 { { 64, kRT, kRGBA, kA, 0, kTL }, { 64, kRT, kRGBA, kA, 0, kBL }, kShare },
Robert Phillips57aa3672017-07-21 11:38:13 -0400215 };
216
217 for (auto test : gNonOverlappingTests) {
Robert Phillips715d08c2018-07-18 13:56:48 -0400218 GrSurfaceProxy* p1 = make_deferred(proxyProvider, test.fP1);
219 GrSurfaceProxy* p2 = make_deferred(proxyProvider, test.fP2);
220
Robert Phillips57aa3672017-07-21 11:38:13 -0400221 if (!p1 || !p2) {
222 continue; // creation can fail (i.e., for msaa4 on iOS)
223 }
Robert Phillips715d08c2018-07-18 13:56:48 -0400224
225 non_overlap_test(reporter, resourceProvider, p1, p2, test.fExpectation);
226
227 p1->completedRead();
228 p2->completedRead();
Robert Phillips57aa3672017-07-21 11:38:13 -0400229 }
230
231 {
232 // Wrapped backend textures should never be reused
233 TestCase t[1] = {
234 { { 64, kNotRT, kRGBA, kE, 0, kTL }, { 64, kNotRT, kRGBA, kE, 0, kTL }, kDontShare }
235 };
236
Robert Phillipsd21b2a52017-12-12 13:01:25 -0500237 GrBackendTexture backEndTex;
Robert Phillips715d08c2018-07-18 13:56:48 -0400238 GrSurfaceProxy* p1 = make_backend(ctxInfo.grContext(), t[0].fP1, &backEndTex);
239 GrSurfaceProxy* p2 = make_deferred(proxyProvider, t[0].fP2);
240
241 non_overlap_test(reporter, resourceProvider, p1, p2, t[0].fExpectation);
242
243 p1->completedRead();
244 p2->completedRead();
245
Brian Salomon26102cb2018-03-09 09:33:19 -0500246 cleanup_backend(ctxInfo.grContext(), backEndTex);
Robert Phillips57aa3672017-07-21 11:38:13 -0400247 }
Robert Phillips4150eea2018-02-07 17:08:21 -0500248
249 resourceProvider->testingOnly_setExplicitlyAllocateGPUResources(orig);
Robert Phillips5af44de2017-07-18 14:49:38 -0400250}
Robert Phillips1734dd32018-08-21 13:52:09 -0400251
252static void draw(GrContext* context) {
253 SkImageInfo ii = SkImageInfo::Make(1024, 1024, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
254
255 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes,
256 ii, 1, kTopLeft_GrSurfaceOrigin, nullptr);
257
258 SkCanvas* c = s->getCanvas();
259
260 c->clear(SK_ColorBLACK);
261}
262
263
264DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ResourceAllocatorStressTest, reporter, ctxInfo) {
265 GrContext* context = ctxInfo.grContext();
266 GrResourceProvider* resourceProvider = ctxInfo.grContext()->contextPriv().resourceProvider();
267
268 int maxNum;
269 size_t maxBytes;
270 context->getResourceCacheLimits(&maxNum, &maxBytes);
271
272 bool orig = resourceProvider->testingOnly_setExplicitlyAllocateGPUResources(true);
273 context->setResourceCacheLimits(0, 0); // We'll always be overbudget
274
275 draw(context);
276 draw(context);
277 draw(context);
278 draw(context);
279 context->flush();
280
281 context->setResourceCacheLimits(maxNum, maxBytes);
282 resourceProvider->testingOnly_setExplicitlyAllocateGPUResources(orig);
283}