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

Commit afc1898

Browse files
[Impeller] mark the end of a frame boundary for system compositor interop. (#53722)
Fixes flutter/flutter#151274 This is only an issue on iOS (so far) because of the platform view rendering strategy that involves submitting multiple impeller frames per compositor frame. FYI @bdero
1 parent 8e2d05f commit afc1898

6 files changed

+53
-10
lines changed

flow/surface_frame.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,13 @@ class SurfaceFrame {
8080
// Time at which this frame is scheduled to be presented. This is a hint
8181
// that can be passed to the platform to drop queued frames.
8282
std::optional<fml::TimePoint> presentation_time;
83+
84+
// Whether this surface frame represents the last in a group frames that
85+
// were submitted as part of a platform compositor interop step, such as
86+
// during iOS platform view compositing.
87+
//
88+
// Defaults to true, which is generally a safe value.
89+
bool frame_boundary = true;
8390
};
8491

8592
bool Submit();

shell/gpu/gpu_surface_gl_impeller.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,14 +127,16 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceGLImpeller::AcquireFrame(
127127
impeller_dispatcher,
128128
SkIRect::MakeWH(cull_rect.width, cull_rect.height));
129129
auto picture = impeller_dispatcher.EndRecordingAsPicture();
130+
const bool reset_host_buffer =
131+
surface_frame.submit_info().frame_boundary;
130132

131133
return renderer->Render(
132134
std::move(surface),
133135
fml::MakeCopyable(
134-
[aiks_context, picture = std::move(picture)](
136+
[aiks_context, picture = std::move(picture), reset_host_buffer](
135137
impeller::RenderTarget& render_target) -> bool {
136138
return aiks_context->Render(picture, render_target,
137-
/*reset_host_buffer=*/true);
139+
reset_host_buffer);
138140
}));
139141
});
140142

shell/gpu/gpu_surface_metal_impeller.mm

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -187,12 +187,13 @@
187187
impeller::DlDispatcher impeller_dispatcher(cull_rect);
188188
display_list->Dispatch(impeller_dispatcher, sk_cull_rect);
189189
auto picture = impeller_dispatcher.EndRecordingAsPicture();
190+
const bool reset_host_buffer = surface_frame.submit_info().frame_boundary;
190191

191192
return renderer->Render(
192193
std::move(surface),
193-
fml::MakeCopyable([aiks_context, picture = std::move(picture)](
194-
impeller::RenderTarget& render_target) -> bool {
195-
return aiks_context->Render(picture, render_target, /*reset_host_buffer=*/true);
194+
fml::MakeCopyable([aiks_context, picture = std::move(picture),
195+
reset_host_buffer](impeller::RenderTarget& render_target) -> bool {
196+
return aiks_context->Render(picture, render_target, reset_host_buffer);
196197
}));
197198
#endif
198199
});
@@ -307,11 +308,12 @@
307308
display_list->Dispatch(impeller_dispatcher, sk_cull_rect);
308309
auto picture = impeller_dispatcher.EndRecordingAsPicture();
309310

311+
const bool reset_host_buffer = surface_frame.submit_info().frame_boundary;
310312
bool render_result = renderer->Render(
311313
std::move(surface),
312-
fml::MakeCopyable([aiks_context, picture = std::move(picture)](
313-
impeller::RenderTarget& render_target) -> bool {
314-
return aiks_context->Render(picture, render_target, /*reset_host_buffer=*/true);
314+
fml::MakeCopyable([aiks_context, picture = std::move(picture),
315+
reset_host_buffer](impeller::RenderTarget& render_target) -> bool {
316+
return aiks_context->Render(picture, render_target, reset_host_buffer);
315317
}));
316318
#endif
317319
if (!render_result) {

shell/gpu/gpu_surface_metal_impeller_unittests.mm

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,5 +97,32 @@ GPUCAMetalLayerHandle GetCAMetalLayer(const SkISize& frame_info) const override
9797
ASSERT_TRUE(frame->Submit());
9898
}
9999

100+
TEST(GPUSurfaceMetalImpeller, ResetHostBufferBasedOnFrameBoundary) {
101+
auto delegate = std::make_shared<TestGPUSurfaceMetalDelegate>();
102+
delegate->SetDevice();
103+
104+
auto context = CreateImpellerContext();
105+
std::unique_ptr<Surface> surface =
106+
std::make_unique<GPUSurfaceMetalImpeller>(delegate.get(), CreateImpellerContext());
107+
108+
ASSERT_TRUE(surface->IsValid());
109+
110+
auto& host_buffer = surface->GetAiksContext()->GetContentContext().GetTransientsBuffer();
111+
112+
EXPECT_EQ(host_buffer.GetStateForTest().current_frame, 0u);
113+
114+
auto frame = surface->AcquireFrame(SkISize::Make(100, 100));
115+
frame->set_submit_info({.frame_boundary = false});
116+
117+
ASSERT_TRUE(frame->Submit());
118+
EXPECT_EQ(host_buffer.GetStateForTest().current_frame, 0u);
119+
120+
frame = surface->AcquireFrame(SkISize::Make(100, 100));
121+
frame->set_submit_info({.frame_boundary = true});
122+
123+
ASSERT_TRUE(frame->Submit());
124+
EXPECT_EQ(host_buffer.GetStateForTest().current_frame, 1u);
125+
}
126+
100127
} // namespace testing
101128
} // namespace flutter

shell/gpu/gpu_surface_vulkan_impeller.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,10 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceVulkanImpeller::AcquireFrame(
117117
impeller_dispatcher,
118118
SkIRect::MakeWH(cull_rect.width, cull_rect.height));
119119
auto picture = impeller_dispatcher.EndRecordingAsPicture();
120-
120+
const bool reset_host_buffer =
121+
surface_frame.submit_info().frame_boundary;
121122
return aiks_context->Render(picture, render_target,
122-
/*reset_host_buffer=*/true);
123+
reset_host_buffer);
123124
#endif
124125
}));
125126
});

shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,10 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
864864
slice->render_into(overlay_canvas);
865865
overlay_canvas->RestoreToCount(restore_count);
866866

867+
// This flutter view is never the last in a frame, since we always submit the
868+
// underlay view last.
869+
frame->set_submit_info({.frame_boundary = false});
870+
867871
layer->did_submit_last_frame = frame->Submit();
868872
return layer;
869873
}

0 commit comments

Comments
 (0)