Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit d7ef306

Browse files
authored
Purge resources on rasterizer teardown (#33890)
1 parent 6e7c645 commit d7ef306

File tree

5 files changed

+158
-54
lines changed

5 files changed

+158
-54
lines changed

shell/common/BUILD.gn

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,11 @@ if (enable_unittests) {
302302
} else {
303303
# TODO(63837): This test is hard-coded to use a TestGLSurface so it cannot run on fuchsia.
304304
sources += [ "shell_io_manager_unittests.cc" ]
305+
306+
# Swiftshader only supports x86/64. Only needed on non-Fuchsia platforms.
307+
if (shell_enable_vulkan && (target_cpu == "x86" || target_cpu == "x64")) {
308+
deps += [ "//third_party/swiftshader_flutter:swiftshader_vulkan" ]
309+
}
305310
}
306311
}
307312
}

shell/common/rasterizer.cc

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,17 @@ void Rasterizer::TeardownExternalViewEmbedder() {
8787
}
8888

8989
void Rasterizer::Teardown() {
90-
auto context_switch =
91-
surface_ ? surface_->MakeRenderContextCurrent() : nullptr;
92-
if (context_switch && context_switch->GetResult()) {
93-
compositor_context_->OnGrContextDestroyed();
90+
if (surface_) {
91+
auto context_switch = surface_->MakeRenderContextCurrent();
92+
if (context_switch->GetResult()) {
93+
compositor_context_->OnGrContextDestroyed();
94+
if (auto* context = surface_->GetContext()) {
95+
context->purgeUnlockedResources(/*scratchResourcesOnly=*/false);
96+
}
97+
}
98+
surface_.reset();
9499
}
95100

96-
surface_.reset();
97101
last_layer_tree_.reset();
98102

99103
if (raster_thread_merger_.get() != nullptr &&

shell/common/rasterizer_unittests.cc

Lines changed: 127 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
using testing::_;
2121
using testing::ByMove;
22+
using testing::NiceMock;
2223
using testing::Return;
2324
using testing::ReturnRef;
2425

@@ -77,7 +78,7 @@ class MockExternalViewEmbedder : public ExternalViewEmbedder {
7778
} // namespace
7879

7980
TEST(RasterizerTest, create) {
80-
MockDelegate delegate;
81+
NiceMock<MockDelegate> delegate;
8182
auto rasterizer = std::make_unique<Rasterizer>(delegate);
8283
EXPECT_TRUE(rasterizer != nullptr);
8384
}
@@ -106,10 +107,10 @@ TEST(RasterizerTest, drawEmptyPipeline) {
106107
thread_host.raster_thread->GetTaskRunner(),
107108
thread_host.ui_thread->GetTaskRunner(),
108109
thread_host.io_thread->GetTaskRunner());
109-
MockDelegate delegate;
110+
NiceMock<MockDelegate> delegate;
110111
ON_CALL(delegate, GetTaskRunners()).WillByDefault(ReturnRef(task_runners));
111112
auto rasterizer = std::make_unique<Rasterizer>(delegate);
112-
auto surface = std::make_unique<MockSurface>();
113+
auto surface = std::make_unique<NiceMock<MockSurface>>();
113114
EXPECT_CALL(*surface, MakeRenderContextCurrent())
114115
.WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(true))));
115116
rasterizer->Setup(std::move(surface));
@@ -133,15 +134,15 @@ TEST(RasterizerTest,
133134
thread_host.raster_thread->GetTaskRunner(),
134135
thread_host.ui_thread->GetTaskRunner(),
135136
thread_host.io_thread->GetTaskRunner());
136-
MockDelegate delegate;
137+
NiceMock<MockDelegate> delegate;
137138
EXPECT_CALL(delegate, GetTaskRunners())
138139
.WillRepeatedly(ReturnRef(task_runners));
139140
EXPECT_CALL(delegate, OnFrameRasterized(_));
140141
auto rasterizer = std::make_unique<Rasterizer>(delegate);
141-
auto surface = std::make_unique<MockSurface>();
142+
auto surface = std::make_unique<NiceMock<MockSurface>>();
142143

143-
std::shared_ptr<MockExternalViewEmbedder> external_view_embedder =
144-
std::make_shared<MockExternalViewEmbedder>();
144+
std::shared_ptr<NiceMock<MockExternalViewEmbedder>> external_view_embedder =
145+
std::make_shared<NiceMock<MockExternalViewEmbedder>>();
145146
rasterizer->SetExternalViewEmbedder(external_view_embedder);
146147

147148
SurfaceFrame::FramebufferInfo framebuffer_info;
@@ -200,14 +201,14 @@ TEST(
200201
thread_host.raster_thread->GetTaskRunner(),
201202
thread_host.ui_thread->GetTaskRunner(),
202203
thread_host.io_thread->GetTaskRunner());
203-
MockDelegate delegate;
204+
NiceMock<MockDelegate> delegate;
204205
EXPECT_CALL(delegate, GetTaskRunners())
205206
.WillRepeatedly(ReturnRef(task_runners));
206207
EXPECT_CALL(delegate, OnFrameRasterized(_));
207208
auto rasterizer = std::make_unique<Rasterizer>(delegate);
208-
auto surface = std::make_unique<MockSurface>();
209-
std::shared_ptr<MockExternalViewEmbedder> external_view_embedder =
210-
std::make_shared<MockExternalViewEmbedder>();
209+
auto surface = std::make_unique<NiceMock<MockSurface>>();
210+
std::shared_ptr<NiceMock<MockExternalViewEmbedder>> external_view_embedder =
211+
std::make_shared<NiceMock<MockExternalViewEmbedder>>();
211212
rasterizer->SetExternalViewEmbedder(external_view_embedder);
212213
EXPECT_CALL(*external_view_embedder, SupportsDynamicThreadMerging)
213214
.WillRepeatedly(Return(true));
@@ -265,16 +266,16 @@ TEST(
265266
thread_host.ui_thread->GetTaskRunner(),
266267
thread_host.io_thread->GetTaskRunner());
267268

268-
MockDelegate delegate;
269+
NiceMock<MockDelegate> delegate;
269270
EXPECT_CALL(delegate, GetTaskRunners())
270271
.WillRepeatedly(ReturnRef(task_runners));
271272
EXPECT_CALL(delegate, OnFrameRasterized(_));
272273

273274
auto rasterizer = std::make_unique<Rasterizer>(delegate);
274-
auto surface = std::make_unique<MockSurface>();
275+
auto surface = std::make_unique<NiceMock<MockSurface>>();
275276

276-
std::shared_ptr<MockExternalViewEmbedder> external_view_embedder =
277-
std::make_shared<MockExternalViewEmbedder>();
277+
std::shared_ptr<NiceMock<MockExternalViewEmbedder>> external_view_embedder =
278+
std::make_shared<NiceMock<MockExternalViewEmbedder>>();
278279
rasterizer->SetExternalViewEmbedder(external_view_embedder);
279280

280281
SurfaceFrame::FramebufferInfo framebuffer_info;
@@ -329,16 +330,16 @@ TEST(RasterizerTest,
329330
thread_host.ui_thread->GetTaskRunner(),
330331
thread_host.io_thread->GetTaskRunner());
331332

332-
MockDelegate delegate;
333+
NiceMock<MockDelegate> delegate;
333334
EXPECT_CALL(delegate, GetTaskRunners())
334335
.WillRepeatedly(ReturnRef(task_runners));
335336
EXPECT_CALL(delegate, OnFrameRasterized(_));
336337

337338
auto rasterizer = std::make_unique<Rasterizer>(delegate);
338-
auto surface = std::make_unique<MockSurface>();
339+
auto surface = std::make_unique<NiceMock<MockSurface>>();
339340

340-
std::shared_ptr<MockExternalViewEmbedder> external_view_embedder =
341-
std::make_shared<MockExternalViewEmbedder>();
341+
std::shared_ptr<NiceMock<MockExternalViewEmbedder>> external_view_embedder =
342+
std::make_shared<NiceMock<MockExternalViewEmbedder>>();
342343
rasterizer->SetExternalViewEmbedder(external_view_embedder);
343344

344345
SurfaceFrame::FramebufferInfo framebuffer_info;
@@ -402,13 +403,13 @@ TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenNoSurfaceIsSet) {
402403
thread_host.raster_thread->GetTaskRunner(),
403404
thread_host.ui_thread->GetTaskRunner(),
404405
thread_host.io_thread->GetTaskRunner());
405-
MockDelegate delegate;
406+
NiceMock<MockDelegate> delegate;
406407
EXPECT_CALL(delegate, GetTaskRunners())
407408
.WillRepeatedly(ReturnRef(task_runners));
408409
auto rasterizer = std::make_unique<Rasterizer>(delegate);
409410

410-
std::shared_ptr<MockExternalViewEmbedder> external_view_embedder =
411-
std::make_shared<MockExternalViewEmbedder>();
411+
std::shared_ptr<NiceMock<MockExternalViewEmbedder>> external_view_embedder =
412+
std::make_shared<NiceMock<MockExternalViewEmbedder>>();
412413
rasterizer->SetExternalViewEmbedder(external_view_embedder);
413414

414415
EXPECT_CALL(
@@ -445,17 +446,17 @@ TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenNotUsedThisFrame) {
445446
thread_host.raster_thread->GetTaskRunner(),
446447
thread_host.ui_thread->GetTaskRunner(),
447448
thread_host.io_thread->GetTaskRunner());
448-
MockDelegate delegate;
449+
NiceMock<MockDelegate> delegate;
449450
EXPECT_CALL(delegate, GetTaskRunners())
450451
.WillRepeatedly(ReturnRef(task_runners));
451452

452453
auto rasterizer = std::make_unique<Rasterizer>(delegate);
453-
auto surface = std::make_unique<MockSurface>();
454+
auto surface = std::make_unique<NiceMock<MockSurface>>();
454455
EXPECT_CALL(*surface, MakeRenderContextCurrent())
455456
.WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(true))));
456457

457-
std::shared_ptr<MockExternalViewEmbedder> external_view_embedder =
458-
std::make_shared<MockExternalViewEmbedder>();
458+
std::shared_ptr<NiceMock<MockExternalViewEmbedder>> external_view_embedder =
459+
std::make_shared<NiceMock<MockExternalViewEmbedder>>();
459460
rasterizer->SetExternalViewEmbedder(external_view_embedder);
460461
rasterizer->Setup(std::move(surface));
461462

@@ -500,17 +501,17 @@ TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenPipelineIsEmpty) {
500501
thread_host.raster_thread->GetTaskRunner(),
501502
thread_host.ui_thread->GetTaskRunner(),
502503
thread_host.io_thread->GetTaskRunner());
503-
MockDelegate delegate;
504+
NiceMock<MockDelegate> delegate;
504505
EXPECT_CALL(delegate, GetTaskRunners())
505506
.WillRepeatedly(ReturnRef(task_runners));
506507

507508
auto rasterizer = std::make_unique<Rasterizer>(delegate);
508-
auto surface = std::make_unique<MockSurface>();
509+
auto surface = std::make_unique<NiceMock<MockSurface>>();
509510
EXPECT_CALL(*surface, MakeRenderContextCurrent())
510511
.WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(true))));
511512

512-
std::shared_ptr<MockExternalViewEmbedder> external_view_embedder =
513-
std::make_shared<MockExternalViewEmbedder>();
513+
std::shared_ptr<NiceMock<MockExternalViewEmbedder>> external_view_embedder =
514+
std::make_shared<NiceMock<MockExternalViewEmbedder>>();
514515
rasterizer->SetExternalViewEmbedder(external_view_embedder);
515516
rasterizer->Setup(std::move(surface));
516517

@@ -543,13 +544,13 @@ TEST(RasterizerTest,
543544
thread_host.raster_thread->GetTaskRunner(),
544545
thread_host.ui_thread->GetTaskRunner(),
545546
thread_host.io_thread->GetTaskRunner());
546-
MockDelegate delegate;
547+
NiceMock<MockDelegate> delegate;
547548
EXPECT_CALL(delegate, GetTaskRunners())
548549
.WillRepeatedly(ReturnRef(task_runners));
549550
EXPECT_CALL(delegate, OnFrameRasterized(_));
550551

551552
auto rasterizer = std::make_unique<Rasterizer>(delegate);
552-
auto surface = std::make_unique<MockSurface>();
553+
auto surface = std::make_unique<NiceMock<MockSurface>>();
553554
auto is_gpu_disabled_sync_switch =
554555
std::make_shared<const fml::SyncSwitch>(false);
555556

@@ -597,12 +598,12 @@ TEST(
597598
thread_host.raster_thread->GetTaskRunner(),
598599
thread_host.ui_thread->GetTaskRunner(),
599600
thread_host.io_thread->GetTaskRunner());
600-
MockDelegate delegate;
601+
NiceMock<MockDelegate> delegate;
601602
EXPECT_CALL(delegate, GetTaskRunners())
602603
.WillRepeatedly(ReturnRef(task_runners));
603604
EXPECT_CALL(delegate, OnFrameRasterized(_));
604605
auto rasterizer = std::make_unique<Rasterizer>(delegate);
605-
auto surface = std::make_unique<MockSurface>();
606+
auto surface = std::make_unique<NiceMock<MockSurface>>();
606607
auto is_gpu_disabled_sync_switch =
607608
std::make_shared<const fml::SyncSwitch>(true);
608609

@@ -652,12 +653,12 @@ TEST(
652653
thread_host.raster_thread->GetTaskRunner(),
653654
thread_host.ui_thread->GetTaskRunner(),
654655
thread_host.io_thread->GetTaskRunner());
655-
MockDelegate delegate;
656+
NiceMock<MockDelegate> delegate;
656657
EXPECT_CALL(delegate, GetTaskRunners())
657658
.WillRepeatedly(ReturnRef(task_runners));
658659
EXPECT_CALL(delegate, OnFrameRasterized(_));
659660
auto rasterizer = std::make_unique<Rasterizer>(delegate);
660-
auto surface = std::make_unique<MockSurface>();
661+
auto surface = std::make_unique<NiceMock<MockSurface>>();
661662
auto is_gpu_disabled_sync_switch =
662663
std::make_shared<const fml::SyncSwitch>(false);
663664

@@ -706,12 +707,12 @@ TEST(
706707
thread_host.raster_thread->GetTaskRunner(),
707708
thread_host.ui_thread->GetTaskRunner(),
708709
thread_host.io_thread->GetTaskRunner());
709-
MockDelegate delegate;
710+
NiceMock<MockDelegate> delegate;
710711
EXPECT_CALL(delegate, GetTaskRunners())
711712
.WillRepeatedly(ReturnRef(task_runners));
712713
EXPECT_CALL(delegate, OnFrameRasterized(_)).Times(0);
713714
auto rasterizer = std::make_unique<Rasterizer>(delegate);
714-
auto surface = std::make_unique<MockSurface>();
715+
auto surface = std::make_unique<NiceMock<MockSurface>>();
715716
auto is_gpu_disabled_sync_switch =
716717
std::make_shared<const fml::SyncSwitch>(true);
717718

@@ -758,7 +759,7 @@ TEST(RasterizerTest,
758759
thread_host.raster_thread->GetTaskRunner(),
759760
thread_host.ui_thread->GetTaskRunner(),
760761
thread_host.io_thread->GetTaskRunner());
761-
MockDelegate delegate;
762+
NiceMock<MockDelegate> delegate;
762763
ON_CALL(delegate, GetTaskRunners()).WillByDefault(ReturnRef(task_runners));
763764

764765
fml::AutoResetWaitableEvent latch;
@@ -769,7 +770,7 @@ TEST(RasterizerTest,
769770
});
770771
latch.Wait();
771772

772-
auto surface = std::make_unique<MockSurface>();
773+
auto surface = std::make_unique<NiceMock<MockSurface>>();
773774
EXPECT_CALL(*surface, AllowsDrawingWhenGpuDisabled())
774775
.WillRepeatedly(Return(true));
775776
ON_CALL(*surface, AcquireFrame(SkISize()))
@@ -831,6 +832,88 @@ TEST(RasterizerTest,
831832
latch.Wait();
832833
}
833834

835+
TEST(RasterizerTest, TeardownFreesResourceCache) {
836+
std::string test_name =
837+
::testing::UnitTest::GetInstance()->current_test_info()->name();
838+
ThreadHost thread_host("io.flutter.test." + test_name + ".",
839+
ThreadHost::Type::Platform | ThreadHost::Type::RASTER |
840+
ThreadHost::Type::IO | ThreadHost::Type::UI);
841+
TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
842+
thread_host.raster_thread->GetTaskRunner(),
843+
thread_host.ui_thread->GetTaskRunner(),
844+
thread_host.io_thread->GetTaskRunner());
845+
846+
NiceMock<MockDelegate> delegate;
847+
EXPECT_CALL(delegate, GetTaskRunners())
848+
.WillRepeatedly(ReturnRef(task_runners));
849+
850+
auto rasterizer = std::make_unique<Rasterizer>(delegate);
851+
auto surface = std::make_unique<NiceMock<MockSurface>>();
852+
auto context = GrDirectContext::MakeMock(nullptr);
853+
context->setResourceCacheLimit(0);
854+
855+
EXPECT_CALL(*surface, MakeRenderContextCurrent())
856+
.WillRepeatedly([]() -> std::unique_ptr<GLContextResult> {
857+
return std::make_unique<GLContextDefaultResult>(true);
858+
});
859+
EXPECT_CALL(*surface, GetContext()).WillRepeatedly(Return(context.get()));
860+
861+
rasterizer->Setup(std::move(surface));
862+
EXPECT_EQ(context->getResourceCacheLimit(), 0ul);
863+
864+
rasterizer->SetResourceCacheMaxBytes(10000000, false);
865+
EXPECT_EQ(context->getResourceCacheLimit(), 10000000ul);
866+
EXPECT_EQ(context->getResourceCachePurgeableBytes(), 0ul);
867+
868+
int count = 0;
869+
size_t bytes = 0;
870+
context->getResourceCacheUsage(&count, &bytes);
871+
EXPECT_EQ(bytes, 0ul);
872+
873+
auto image_info =
874+
SkImageInfo::MakeN32Premul(500, 500, SkColorSpace::MakeSRGB());
875+
auto sk_surface =
876+
SkSurface::MakeRenderTarget(context.get(), SkBudgeted::kYes, image_info);
877+
EXPECT_TRUE(sk_surface);
878+
879+
SkPaint paint;
880+
sk_surface->getCanvas()->drawPaint(paint);
881+
sk_surface->getCanvas()->flush();
882+
context->flushAndSubmit(true);
883+
884+
EXPECT_EQ(context->getResourceCachePurgeableBytes(), 0ul);
885+
886+
sk_surface.reset();
887+
888+
context->getResourceCacheUsage(&count, &bytes);
889+
EXPECT_GT(bytes, 0ul);
890+
EXPECT_GT(context->getResourceCachePurgeableBytes(), 0ul);
891+
892+
rasterizer->Teardown();
893+
EXPECT_EQ(context->getResourceCachePurgeableBytes(), 0ul);
894+
}
895+
896+
TEST(RasterizerTest, TeardownNoSurface) {
897+
std::string test_name =
898+
::testing::UnitTest::GetInstance()->current_test_info()->name();
899+
ThreadHost thread_host("io.flutter.test." + test_name + ".",
900+
ThreadHost::Type::Platform | ThreadHost::Type::RASTER |
901+
ThreadHost::Type::IO | ThreadHost::Type::UI);
902+
TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
903+
thread_host.raster_thread->GetTaskRunner(),
904+
thread_host.ui_thread->GetTaskRunner(),
905+
thread_host.io_thread->GetTaskRunner());
906+
907+
NiceMock<MockDelegate> delegate;
908+
EXPECT_CALL(delegate, GetTaskRunners())
909+
.WillRepeatedly(ReturnRef(task_runners));
910+
911+
auto rasterizer = std::make_unique<Rasterizer>(delegate);
912+
913+
EXPECT_TRUE(rasterizer);
914+
rasterizer->Teardown();
915+
}
916+
834917
TEST(RasterizerTest, presentationTimeSetWhenVsyncTargetInFuture) {
835918
std::string test_name =
836919
::testing::UnitTest::GetInstance()->current_test_info()->name();
@@ -841,7 +924,8 @@ TEST(RasterizerTest, presentationTimeSetWhenVsyncTargetInFuture) {
841924
thread_host.raster_thread->GetTaskRunner(),
842925
thread_host.ui_thread->GetTaskRunner(),
843926
thread_host.io_thread->GetTaskRunner());
844-
MockDelegate delegate;
927+
928+
NiceMock<MockDelegate> delegate;
845929
ON_CALL(delegate, GetTaskRunners()).WillByDefault(ReturnRef(task_runners));
846930

847931
fml::AutoResetWaitableEvent latch;
@@ -920,7 +1004,8 @@ TEST(RasterizerTest, presentationTimeNotSetWhenVsyncTargetInPast) {
9201004
thread_host.raster_thread->GetTaskRunner(),
9211005
thread_host.ui_thread->GetTaskRunner(),
9221006
thread_host.io_thread->GetTaskRunner());
923-
MockDelegate delegate;
1007+
1008+
NiceMock<MockDelegate> delegate;
9241009
ON_CALL(delegate, GetTaskRunners()).WillByDefault(ReturnRef(task_runners));
9251010

9261011
fml::AutoResetWaitableEvent latch;

0 commit comments

Comments
 (0)