Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Prev Previous commit
Next Next commit
Removed the optimization, fixed local padding calculation
  • Loading branch information
gaaclarke committed Dec 20, 2023
commit 8947a453f24b46cd8071f5ed15ab3bd61edb74b7
1 change: 0 additions & 1 deletion impeller/aiks/aiks_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3930,6 +3930,5 @@ TEST_P(AiksTest, SubpassWithClearColorOptimization) {
// will be filled with NaNs and may produce a magenta texture on macOS or iOS.
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}

} // namespace testing
} // namespace impeller
44 changes: 16 additions & 28 deletions impeller/entity/contents/filters/gaussian_blur_filter_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,6 @@ using GaussianBlurFragmentShader = GaussianBlurPipeline::FragmentShader;

namespace {

std::optional<Rect> ExpandCoverageHint(const std::optional<Rect>& coverage_hint,
const Matrix& source_to_local_transform,
const Vector2& padding) {
if (!coverage_hint.has_value()) {
return std::nullopt;
}
Vector2 transformed_padding = (source_to_local_transform * padding).Abs();
return coverage_hint->Expand(transformed_padding);
}

SamplerDescriptor MakeSamplerDescriptor(MinMagFilter filter,
SamplerAddressMode address_mode) {
SamplerDescriptor sampler_desc;
Expand Down Expand Up @@ -253,20 +243,23 @@ std::optional<Entity> GaussianBlurFilterContents::RenderFilter(
Vector2 blur_radius = {CalculateBlurRadius(scaled_sigma.x),
CalculateBlurRadius(scaled_sigma.y)};
Vector2 padding(ceil(blur_radius.x), ceil(blur_radius.y));
Vector2 local_padding =
(entity.GetTransform().Basis() * effect_transform.Basis() * padding).Abs();

// Apply as much of the desired padding as possible from the source. This may
// be ignored so must be accounted for in the downsample pass by adding a
// transparent gutter.
std::optional<Rect> expanded_coverage_hint = ExpandCoverageHint(
coverage_hint, entity.GetTransform() * effect_transform, padding);
std::optional<Rect> expanded_coverage_hint;
if (coverage_hint.has_value()) {
expanded_coverage_hint = coverage_hint->Expand(local_padding);
}

std::optional<Snapshot> input_snapshot =
inputs[0]->GetSnapshot("GaussianBlur", renderer, entity,
/*coverage_limit=*/expanded_coverage_hint);
if (!input_snapshot.has_value()) {
return std::nullopt;
}
std::optional<Rect> input_snapshot_coverage = input_snapshot->GetCoverage();

if (scaled_sigma.x < kEhCloseEnough && scaled_sigma.y < kEhCloseEnough) {
return Entity::FromSnapshot(input_snapshot.value(), entity.GetBlendMode(),
Expand All @@ -280,22 +273,17 @@ std::optional<Entity> GaussianBlurFilterContents::RenderFilter(
// pass.
Vector2 downsample_scalar(desired_scalar, desired_scalar);
Rect source_rect = Rect::MakeSize(input_snapshot->texture->GetSize());
Rect source_rect_padded = source_rect;
Matrix padding_snapshot_adjustment;
if (!coverage_hint.has_value() ||
(input_snapshot_coverage.has_value() &&
!input_snapshot_coverage->Contains(coverage_hint.value()))) {
// This means that the snapshot does not contain all the data it needs to
// render, so we add extra padding for the blur halo to render.
// TODO(gaaclarke): This adds a gutter for the blur halo that is uniform,
// if we could only add padding where necessary that would
// be more efficient.
source_rect_padded = source_rect_padded.Expand(padding);
padding_snapshot_adjustment = Matrix::MakeTranslation(-padding);
}
Rect source_rect_padded = source_rect.Expand(padding);
Matrix padding_snapshot_adjustment = Matrix::MakeTranslation(-padding);
// TODO(gaaclarke): The padding could be removed if we know it's not needed or
// resized to account for the expanded_clip_coverage. There doesn't appear
// to be the math to make those calculations though. The following
// optimization works, but causes a shimmer as a result of
// https://github.com/flutter/flutter/issues/140193 so it isn't applied.
//
// !input_snapshot->GetCoverage()->Expand(-local_padding)
// .Contains(coverage_hint.value()))
Vector2 downsampled_size = source_rect_padded.size * downsample_scalar;
// TODO(gaaclarke): I don't think we are correctly handling this fractional
// amount we are throwing away.
ISize subpass_size =
ISize(round(downsampled_size.x), round(downsampled_size.y));
Vector2 effective_scalar = Vector2(subpass_size) / source_rect_padded.size;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,40 +205,6 @@ TEST_P(GaussianBlurFilterContentsTest, RenderCoverageMatchesGetCoverage) {
}
}

TEST_P(GaussianBlurFilterContentsTest, RenderCoverageNoBlurHalo) {
TextureDescriptor desc = {
.storage_mode = StorageMode::kDevicePrivate,
.format = PixelFormat::kB8G8R8A8UNormInt,
.size = ISize(100, 100),
};
std::shared_ptr<Texture> texture = MakeTexture(desc);
Scalar sigma_radius_1 = CalculateSigmaForBlurRadius(1.0);
auto contents = std::make_unique<GaussianBlurFilterContents>(
sigma_radius_1, sigma_radius_1, Entity::TileMode::kDecal);
contents->SetInputs({FilterInput::Make(texture)});
std::shared_ptr<ContentContext> renderer = GetContentContext();

Entity entity;
std::optional<Entity> result = contents->GetEntity(
*renderer, entity, /*coverage_hint=*/Rect::MakeLTRB(25, 25, 75, 75));
EXPECT_TRUE(result.has_value());
if (result.has_value()) {
EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
std::optional<Rect> result_coverage = result.value().GetCoverage();
std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
EXPECT_TRUE(result_coverage.has_value());
EXPECT_TRUE(contents_coverage.has_value());
if (result_coverage.has_value() && contents_coverage.has_value()) {
EXPECT_TRUE(RectNear(contents_coverage.value(),
Rect::MakeLTRB(-1, -1, 101, 101)));
// The result coverage is inside the coverage as a result of an
// optimization that avoids adding a halo gutter.
EXPECT_TRUE(
RectNear(result_coverage.value(), Rect::MakeLTRB(0, 0, 100, 100)));
}
}
}

TEST_P(GaussianBlurFilterContentsTest,
RenderCoverageMatchesGetCoverageTranslate) {
TextureDescriptor desc = {
Expand Down
3 changes: 2 additions & 1 deletion impeller/geometry/rect.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ struct TRect {
}

constexpr bool Contains(const TRect& o) const {
return Union(o).size == size;
return o.GetLeft() >= GetLeft() && o.GetTop() >= GetTop() &&
o.GetRight() <= GetRight() && o.GetBottom() <= GetBottom();
}

/// Returns true if either of the width or height are 0, negative, or NaN.
Expand Down