Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 6 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
23 changes: 23 additions & 0 deletions impeller/aiks/aiks_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3867,6 +3867,29 @@ TEST_P(AiksTest, GaussianBlurMipMapImageFilter) {
#endif
}

TEST_P(AiksTest, SaveLayersCloseToRootPassSizeAreScaledUp) {
Canvas canvas;
canvas.SaveLayer(
{
.color = Color::Black().WithAlpha(0.5),
},
Rect::MakeSize(ISize(95, 95)));
canvas.DrawRect(Rect::MakeLTRB(0, 0, 100, 100), {.color = Color::Red()});
canvas.DrawRect(Rect::MakeLTRB(50, 50, 150, 150), {.color = Color::Blue()});
canvas.Restore();

Picture picture = canvas.EndRecordingAsPicture();
std::shared_ptr<RenderTargetCache> cache =
std::make_shared<RenderTargetCache>(GetContext()->GetResourceAllocator());
AiksContext aiks_context(GetContext(), nullptr, cache);
picture.ToImage(aiks_context, {100, 100});

for (auto it = cache->GetTextureDataBegin(); it != cache->GetTextureDataEnd();
++it) {
EXPECT_EQ(it->texture->GetTextureDescriptor().size, ISize(100, 100));
}
}

TEST_P(AiksTest, ImageColorSourceEffectTransform) {
// Compare with https://fiddle.skia.org/c/6cdc5aefb291fda3833b806ca347a885

Expand Down
13 changes: 13 additions & 0 deletions impeller/entity/entity_pass.cc
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,19 @@ EntityPass::EntityResult EntityPass::GetEntityForElement(
return EntityPass::EntityResult::Skip();
}

// When a subpass size is close to, but still smaller than the root pass
// size, we may scale it up to the root pass size. This will improve
// performance by improving the efficiency of the render target cache, as
// only textures with exactly the same sizes + descriptors can be recycled.
if (subpass_size.width < root_pass_size.width &&
subpass_size.height < root_pass_size.height &&
root_pass_size.width - subpass_size.width <=
(0.1 * subpass_size.width) &&
root_pass_size.height - subpass_size.height <=
(0.1 * subpass_size.height)) {
subpass_size = root_pass_size;
Copy link
Member

@bdero bdero Jan 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs more changes to make it safe.

I think the clear color optimization will always work out to be safe even thought it uses the root pass size, since it should fill up to the next largest clip anyhow.

Something that's not safe is the SaveLayer bounds hint. We simply use the bounds hint to limit the subpass, relying on the root pass to clip content outside of the bounds. So when a bounds hint is supplied we need to insert a clip to keep the behavior consistent with Skia.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the case I'm concerned about, the bounds hint is actually the same size as the root pass size. So it sounds like I can handle this by only rounding up if I don't round up past the bounds hint, correct?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need a golden case that creates a SaveLayer with the bounds limit supplied and tries to draw stuff outside all the edges of the subpass.

Copy link
Member

@bdero bdero Jan 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh sorry, it's 2024 and GitHub isn't ajax yet, so I didn't see your last message.

Copy link
Member

@bdero bdero Jan 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bounds hint is in local space, but the output of GetSubpassCoverage (used to determine the size of the texture) is in screen space. So I think you could safely check this for your case by subpass.bounds_limit_->TransformBounds(subpass.transform_).GetSize() >= subpass_size. GetSubpassCoverage does this to work out the screen space bounds for clamping the texture, so to avoid float issues I'd make sure both places use the exact same rectangle (by sharing the same code path or computed output).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or if you happen to know that the bounds hint will never be supplied for the zoom page transition layers, just check that it's nullopt?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is a bounds hint, its just the same as the root pass size. I'll need to check if its smaller than the root pass size.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done...ish

}

auto subpass_target = CreateRenderTarget(
renderer, // renderer
subpass_size, // size
Expand Down