blob: 4c2fbd0b6a2067fdf9737affecf29b1583125ee2 [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 "GrTest.h"
19#include "GrTexture.h"
Robert Phillips5af44de2017-07-18 14:49:38 -040020#include "GrTextureProxy.h"
Greg Daniel4684f822018-03-08 15:27:36 -050021#include "GrUninstantiateProxyTracker.h"
Robert Phillips5af44de2017-07-18 14:49:38 -040022
Robert Phillips1734dd32018-08-21 13:52:09 -040023#include "SkSurface.h"
24
Robert Phillips57aa3672017-07-21 11:38:13 -040025struct ProxyParams {
26 int fSize;
27 bool fIsRT;
28 GrPixelConfig fConfig;
29 SkBackingFit fFit;
30 int fSampleCnt;
31 GrSurfaceOrigin fOrigin;
32 // TODO: do we care about mipmapping
33};
34
Robert Phillips715d08c2018-07-18 13:56:48 -040035static GrSurfaceProxy* make_deferred(GrProxyProvider* proxyProvider, const ProxyParams& p) {
Robert Phillips57aa3672017-07-21 11:38:13 -040036 GrSurfaceDesc desc;
37 desc.fFlags = p.fIsRT ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags;
Robert Phillips57aa3672017-07-21 11:38:13 -040038 desc.fWidth = p.fSize;
39 desc.fHeight = p.fSize;
40 desc.fConfig = p.fConfig;
41 desc.fSampleCnt = p.fSampleCnt;
42
Robert Phillips715d08c2018-07-18 13:56:48 -040043 auto tmp = proxyProvider->createProxy(desc, p.fOrigin, p.fFit, SkBudgeted::kNo);
44 if (!tmp) {
45 return nullptr;
46 }
47 GrSurfaceProxy* ret = tmp.release();
48
49 // Add a read to keep the proxy around but unref it so its backing surfaces can be recycled
50 ret->addPendingRead();
51 ret->unref();
52 return ret;
Robert Phillips57aa3672017-07-21 11:38:13 -040053}
54
Robert Phillips715d08c2018-07-18 13:56:48 -040055static GrSurfaceProxy* make_backend(GrContext* context, const ProxyParams& p,
56 GrBackendTexture* backendTex) {
Robert Phillips0bd24dc2018-01-16 08:06:32 -050057 GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
Robert Phillipsf35fd8d2018-01-22 10:48:15 -050058 GrGpu* gpu = context->contextPriv().getGpu();
Robert Phillips0bd24dc2018-01-16 08:06:32 -050059
Robert Phillipsf35fd8d2018-01-22 10:48:15 -050060 *backendTex = gpu->createTestingOnlyBackendTexture(nullptr, p.fSize, p.fSize,
61 p.fConfig, false,
62 GrMipMapped::kNo);
Robert Phillips57aa3672017-07-21 11:38:13 -040063
Robert Phillips715d08c2018-07-18 13:56:48 -040064 auto tmp = proxyProvider->wrapBackendTexture(*backendTex, p.fOrigin);
65 if (!tmp) {
66 return nullptr;
67 }
68 GrSurfaceProxy* ret = tmp.release();
69
70 // Add a read to keep the proxy around but unref it so its backing surfaces can be recycled
71 ret->addPendingRead();
72 ret->unref();
73 return ret;
Robert Phillips57aa3672017-07-21 11:38:13 -040074}
75
Brian Salomon26102cb2018-03-09 09:33:19 -050076static void cleanup_backend(GrContext* context, const GrBackendTexture& backendTex) {
Robert Phillipsf35fd8d2018-01-22 10:48:15 -050077 context->contextPriv().getGpu()->deleteTestingOnlyBackendTexture(backendTex);
Robert Phillips57aa3672017-07-21 11:38:13 -040078}
79
Robert Phillips5af44de2017-07-18 14:49:38 -040080// Basic test that two proxies with overlapping intervals and compatible descriptors are
81// assigned different GrSurfaces.
Robert Phillips57aa3672017-07-21 11:38:13 -040082static void overlap_test(skiatest::Reporter* reporter, GrResourceProvider* resourceProvider,
Robert Phillips715d08c2018-07-18 13:56:48 -040083 GrSurfaceProxy* p1, GrSurfaceProxy* p2, bool expectedResult) {
Robert Phillips5af44de2017-07-18 14:49:38 -040084 GrResourceAllocator alloc(resourceProvider);
85
Robert Phillips715d08c2018-07-18 13:56:48 -040086 alloc.addInterval(p1, 0, 4);
87 alloc.addInterval(p2, 1, 2);
Robert Phillipseafd48a2017-11-16 07:52:08 -050088 alloc.markEndOfOpList(0);
Robert Phillips5af44de2017-07-18 14:49:38 -040089
Robert Phillipseafd48a2017-11-16 07:52:08 -050090 int startIndex, stopIndex;
Greg Danielaa3dfbe2018-01-29 10:34:25 -050091 GrResourceAllocator::AssignError error;
Greg Daniel4684f822018-03-08 15:27:36 -050092 GrUninstantiateProxyTracker uninstantiateTracker;
93 alloc.assign(&startIndex, &stopIndex, &uninstantiateTracker, &error);
Greg Danielaa3dfbe2018-01-29 10:34:25 -050094 REPORTER_ASSERT(reporter, GrResourceAllocator::AssignError::kNoError == error);
Robert Phillips5af44de2017-07-18 14:49:38 -040095
Brian Salomonfd98c2c2018-07-31 17:25:29 -040096 REPORTER_ASSERT(reporter, p1->peekSurface());
97 REPORTER_ASSERT(reporter, p2->peekSurface());
Robert Phillips57aa3672017-07-21 11:38:13 -040098 bool doTheBackingStoresMatch = p1->underlyingUniqueID() == p2->underlyingUniqueID();
99 REPORTER_ASSERT(reporter, expectedResult == doTheBackingStoresMatch);
Robert Phillips5af44de2017-07-18 14:49:38 -0400100}
101
Robert Phillips57aa3672017-07-21 11:38:13 -0400102// Test various cases when two proxies do not have overlapping intervals.
103// This mainly acts as a test of the ResourceAllocator's free pool.
104static void non_overlap_test(skiatest::Reporter* reporter, GrResourceProvider* resourceProvider,
Robert Phillips715d08c2018-07-18 13:56:48 -0400105 GrSurfaceProxy* p1, GrSurfaceProxy* p2,
Robert Phillips57aa3672017-07-21 11:38:13 -0400106 bool expectedResult) {
107 GrResourceAllocator alloc(resourceProvider);
108
Robert Phillips715d08c2018-07-18 13:56:48 -0400109 alloc.addInterval(p1, 0, 2);
110 alloc.addInterval(p2, 3, 5);
Robert Phillipseafd48a2017-11-16 07:52:08 -0500111 alloc.markEndOfOpList(0);
Robert Phillips57aa3672017-07-21 11:38:13 -0400112
Robert Phillipseafd48a2017-11-16 07:52:08 -0500113 int startIndex, stopIndex;
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500114 GrResourceAllocator::AssignError error;
Greg Daniel4684f822018-03-08 15:27:36 -0500115 GrUninstantiateProxyTracker uninstantiateTracker;
116 alloc.assign(&startIndex, &stopIndex, &uninstantiateTracker, &error);
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500117 REPORTER_ASSERT(reporter, GrResourceAllocator::AssignError::kNoError == error);
Robert Phillips57aa3672017-07-21 11:38:13 -0400118
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400119 REPORTER_ASSERT(reporter, p1->peekSurface());
120 REPORTER_ASSERT(reporter, p2->peekSurface());
Robert Phillips57aa3672017-07-21 11:38:13 -0400121 bool doTheBackingStoresMatch = p1->underlyingUniqueID() == p2->underlyingUniqueID();
122 REPORTER_ASSERT(reporter, expectedResult == doTheBackingStoresMatch);
123}
124
Robert Phillips4150eea2018-02-07 17:08:21 -0500125bool GrResourceProvider::testingOnly_setExplicitlyAllocateGPUResources(bool newValue) {
126 bool oldValue = fExplicitlyAllocateGPUResources;
127 fExplicitlyAllocateGPUResources = newValue;
128 return oldValue;
129}
130
Robert Phillips57aa3672017-07-21 11:38:13 -0400131DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ResourceAllocatorTest, reporter, ctxInfo) {
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500132 GrProxyProvider* proxyProvider = ctxInfo.grContext()->contextPriv().proxyProvider();
Robert Phillips6be756b2018-01-16 15:07:54 -0500133 GrResourceProvider* resourceProvider = ctxInfo.grContext()->contextPriv().resourceProvider();
Robert Phillips5af44de2017-07-18 14:49:38 -0400134
Robert Phillips4150eea2018-02-07 17:08:21 -0500135 bool orig = resourceProvider->testingOnly_setExplicitlyAllocateGPUResources(true);
136
Robert Phillips57aa3672017-07-21 11:38:13 -0400137 struct TestCase {
138 ProxyParams fP1;
139 ProxyParams fP2;
140 bool fExpectation;
141 };
142
143 constexpr bool kRT = true;
144 constexpr bool kNotRT = false;
145
146 constexpr bool kShare = true;
147 constexpr bool kDontShare = false;
148 // Non-RT GrSurfaces are never recycled on some platforms.
149 bool kConditionallyShare = resourceProvider->caps()->reuseScratchTextures();
150
151 const GrPixelConfig kRGBA = kRGBA_8888_GrPixelConfig;
152 const GrPixelConfig kBGRA = kBGRA_8888_GrPixelConfig;
153
154 const SkBackingFit kE = SkBackingFit::kExact;
155 const SkBackingFit kA = SkBackingFit::kApprox;
156
157 const GrSurfaceOrigin kTL = kTopLeft_GrSurfaceOrigin;
158 const GrSurfaceOrigin kBL = kBottomLeft_GrSurfaceOrigin;
159
160 //--------------------------------------------------------------------------------------------
161 TestCase gOverlappingTests[] = {
162 //----------------------------------------------------------------------------------------
163 // Two proxies with overlapping intervals and compatible descriptors should never share
164 // RT version
165 { { 64, kRT, kRGBA, kA, 0, kTL }, { 64, kRT, kRGBA, kA, 0, kTL }, kDontShare },
166 // non-RT version
167 { { 64, kNotRT, kRGBA, kA, 0, kTL }, { 64, kNotRT, kRGBA, kA, 0, kTL }, kDontShare },
168 };
169
170 for (auto test : gOverlappingTests) {
Robert Phillips715d08c2018-07-18 13:56:48 -0400171 GrSurfaceProxy* p1 = make_deferred(proxyProvider, test.fP1);
172 GrSurfaceProxy* p2 = make_deferred(proxyProvider, test.fP2);
173 overlap_test(reporter, resourceProvider, p1, p2, test.fExpectation);
174 p1->completedRead();
175 p2->completedRead();
Robert Phillips57aa3672017-07-21 11:38:13 -0400176 }
177
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400178 int k2 = ctxInfo.grContext()->contextPriv().caps()->getRenderTargetSampleCount(2, kRGBA);
179 int k4 = ctxInfo.grContext()->contextPriv().caps()->getRenderTargetSampleCount(4, kRGBA);
Robert Phillips57aa3672017-07-21 11:38:13 -0400180
181 //--------------------------------------------------------------------------------------------
182 TestCase gNonOverlappingTests[] = {
183 //----------------------------------------------------------------------------------------
184 // Two non-overlapping intervals w/ compatible proxies should share
185 // both same size & approx
186 { { 64, kRT, kRGBA, kA, 0, kTL }, { 64, kRT, kRGBA, kA, 0, kTL }, kShare },
187 { { 64, kNotRT, kRGBA, kA, 0, kTL }, { 64, kNotRT, kRGBA, kA, 0, kTL }, kConditionallyShare },
188 // diffs sizes but still approx
189 { { 64, kRT, kRGBA, kA, 0, kTL }, { 50, kRT, kRGBA, kA, 0, kTL }, kShare },
190 { { 64, kNotRT, kRGBA, kA, 0, kTL }, { 50, kNotRT, kRGBA, kA, 0, kTL }, kConditionallyShare },
191 // sames sizes but exact
192 { { 64, kRT, kRGBA, kE, 0, kTL }, { 64, kRT, kRGBA, kE, 0, kTL }, kShare },
193 { { 64, kNotRT, kRGBA, kE, 0, kTL }, { 64, kNotRT, kRGBA, kE, 0, kTL }, kConditionallyShare },
194 //----------------------------------------------------------------------------------------
195 // Two non-overlapping intervals w/ different exact sizes should not share
196 { { 56, kRT, kRGBA, kE, 0, kTL }, { 54, kRT, kRGBA, kE, 0, kTL }, kDontShare },
197 // Two non-overlapping intervals w/ _very different_ approx sizes should not share
198 { { 255, kRT, kRGBA, kA, 0, kTL }, { 127, kRT, kRGBA, kA, 0, kTL }, kDontShare },
199 // Two non-overlapping intervals w/ different MSAA sample counts should not share
200 { { 64, kRT, kRGBA, kA, k2, kTL },{ 64, kRT, kRGBA, kA, k4, kTL}, k2 == k4 },
201 // Two non-overlapping intervals w/ different configs should not share
202 { { 64, kRT, kRGBA, kA, 0, kTL }, { 64, kRT, kBGRA, kA, 0, kTL }, kDontShare },
203 // Two non-overlapping intervals w/ different RT classifications should never share
204 { { 64, kRT, kRGBA, kA, 0, kTL }, { 64, kNotRT, kRGBA, kA, 0, kTL }, kDontShare },
205 { { 64, kNotRT, kRGBA, kA, 0, kTL }, { 64, kRT, kRGBA, kA, 0, kTL }, kDontShare },
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400206 // Two non-overlapping intervals w/ different origins should share
207 { { 64, kRT, kRGBA, kA, 0, kTL }, { 64, kRT, kRGBA, kA, 0, kBL }, kShare },
Robert Phillips57aa3672017-07-21 11:38:13 -0400208 };
209
210 for (auto test : gNonOverlappingTests) {
Robert Phillips715d08c2018-07-18 13:56:48 -0400211 GrSurfaceProxy* p1 = make_deferred(proxyProvider, test.fP1);
212 GrSurfaceProxy* p2 = make_deferred(proxyProvider, test.fP2);
213
Robert Phillips57aa3672017-07-21 11:38:13 -0400214 if (!p1 || !p2) {
215 continue; // creation can fail (i.e., for msaa4 on iOS)
216 }
Robert Phillips715d08c2018-07-18 13:56:48 -0400217
218 non_overlap_test(reporter, resourceProvider, p1, p2, test.fExpectation);
219
220 p1->completedRead();
221 p2->completedRead();
Robert Phillips57aa3672017-07-21 11:38:13 -0400222 }
223
224 {
225 // Wrapped backend textures should never be reused
226 TestCase t[1] = {
227 { { 64, kNotRT, kRGBA, kE, 0, kTL }, { 64, kNotRT, kRGBA, kE, 0, kTL }, kDontShare }
228 };
229
Robert Phillipsd21b2a52017-12-12 13:01:25 -0500230 GrBackendTexture backEndTex;
Robert Phillips715d08c2018-07-18 13:56:48 -0400231 GrSurfaceProxy* p1 = make_backend(ctxInfo.grContext(), t[0].fP1, &backEndTex);
232 GrSurfaceProxy* p2 = make_deferred(proxyProvider, t[0].fP2);
233
234 non_overlap_test(reporter, resourceProvider, p1, p2, t[0].fExpectation);
235
236 p1->completedRead();
237 p2->completedRead();
238
Brian Salomon26102cb2018-03-09 09:33:19 -0500239 cleanup_backend(ctxInfo.grContext(), backEndTex);
Robert Phillips57aa3672017-07-21 11:38:13 -0400240 }
Robert Phillips4150eea2018-02-07 17:08:21 -0500241
242 resourceProvider->testingOnly_setExplicitlyAllocateGPUResources(orig);
Robert Phillips5af44de2017-07-18 14:49:38 -0400243}
Robert Phillips1734dd32018-08-21 13:52:09 -0400244
245static void draw(GrContext* context) {
246 SkImageInfo ii = SkImageInfo::Make(1024, 1024, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
247
248 sk_sp<SkSurface> s = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes,
249 ii, 1, kTopLeft_GrSurfaceOrigin, nullptr);
250
251 SkCanvas* c = s->getCanvas();
252
253 c->clear(SK_ColorBLACK);
254}
255
256
257DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ResourceAllocatorStressTest, reporter, ctxInfo) {
258 GrContext* context = ctxInfo.grContext();
259 GrResourceProvider* resourceProvider = ctxInfo.grContext()->contextPriv().resourceProvider();
260
261 int maxNum;
262 size_t maxBytes;
263 context->getResourceCacheLimits(&maxNum, &maxBytes);
264
265 bool orig = resourceProvider->testingOnly_setExplicitlyAllocateGPUResources(true);
266 context->setResourceCacheLimits(0, 0); // We'll always be overbudget
267
268 draw(context);
269 draw(context);
270 draw(context);
271 draw(context);
272 context->flush();
273
274 context->setResourceCacheLimits(maxNum, maxBytes);
275 resourceProvider->testingOnly_setExplicitlyAllocateGPUResources(orig);
276}