Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Impeller] Ensure that reused textures are cleared before getting sampled by backdrop textures #46084

Merged
merged 2 commits into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions impeller/aiks/aiks_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2264,6 +2264,30 @@ TEST_P(AiksTest, DrawPaintAbsorbsClears) {
ASSERT_EQ(render_pass->GetCommands().size(), 0llu);
}

// This is important to enforce with texture reuse, since cached textures need
// to be cleared before reuse.
TEST_P(AiksTest,
ParentSaveLayerCreatesRenderPassWhenChildBackdropFilterIsPresent) {
Canvas canvas;
canvas.SaveLayer({}, std::nullopt, ImageFilter::MakeMatrix(Matrix(), {}));
canvas.DrawPaint({.color = Color::Red(), .blend_mode = BlendMode::kSource});
canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
.blend_mode = BlendMode::kSourceOver});
canvas.Restore();

Picture picture = canvas.EndRecordingAsPicture();

std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
std::shared_ptr<Context> real_context = GetContext();
std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
AiksContext renderer(mock_context, nullptr);
std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});

ASSERT_EQ(spy->render_passes_.size(), 3llu);
std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
ASSERT_EQ(render_pass->GetCommands().size(), 0llu);
}

TEST_P(AiksTest, DrawRectAbsorbsClears) {
Canvas canvas;
canvas.DrawRect({0, 0, 300, 300},
Expand Down
8 changes: 8 additions & 0 deletions impeller/entity/entity_pass.cc
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,14 @@ EntityPass::EntityResult EntityPass::GetEntityForElement(
proc(FilterInput::Make(std::move(texture)),
subpass->xformation_.Basis(), Entity::RenderingMode::kSubpass);

// If the very first thing we render in this EntityPass is a subpass that
// happens to have a backdrop filter, than that backdrop filter will end
// may wind up sampling from the raw, uncleared texture that came straight
// out of the texture cache. By calling `pass_context.GetRenderPass` here,
// we force the texture to pass through at least one RenderPass with the
// correct clear configuration before any sampling occurs.
pass_context.GetRenderPass(pass_depth);

// The subpass will need to read from the current pass texture when
// rendering the backdrop, so if there's an active pass, end it prior to
// rendering the subpass.
Expand Down