Skip to content

Commit fc4f281

Browse files
author
Shan Huang
committed
Tweak Kawase2 to use fewer passes and fewer samples.
Test: atest librenderengine_bench Bug: 353826438 Flag: EXEMPT behind sysprop flag already Change-Id: Ifcc4e76aa35eb0793734e085ccaeba7d468e4bce
1 parent f0b5cee commit fc4f281

1 file changed

Lines changed: 30 additions & 23 deletions

File tree

libs/renderengine/skia/filters/KawaseBlurDualFilter.cpp

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,17 @@ void KawaseBlurDualFilter::blurInto(const sk_sp<SkSurface>& drawSurface,
9696
void KawaseBlurDualFilter::blurInto(const sk_sp<SkSurface>& drawSurface, sk_sp<SkShader> input,
9797
const float inverseScale, const float radius,
9898
const float alpha) const {
99-
SkRuntimeShaderBuilder blurBuilder(mBlurEffect);
100-
blurBuilder.child("child") = std::move(input);
101-
blurBuilder.uniform("in_inverseScale") = inverseScale;
102-
blurBuilder.uniform("in_blurOffset") = radius;
103-
blurBuilder.uniform("in_crossFade") = alpha;
10499
SkPaint paint;
105-
paint.setShader(blurBuilder.makeShader(nullptr));
100+
if (radius == 0) {
101+
paint.setShader(std::move(input));
102+
paint.setAlphaf(alpha);
103+
} else {
104+
SkRuntimeShaderBuilder blurBuilder(mBlurEffect);
105+
blurBuilder.child("child") = std::move(input);
106+
blurBuilder.uniform("in_blurOffset") = radius;
107+
blurBuilder.uniform("in_crossFade") = alpha;
108+
paint.setShader(blurBuilder.makeShader(nullptr));
109+
}
106110
paint.setBlendMode(alpha == 1.0f ? SkBlendMode::kSrc : SkBlendMode::kSrcOver);
107111
drawSurface->getCanvas()->drawPaint(paint);
108112
}
@@ -116,32 +120,35 @@ sk_sp<SkImage> KawaseBlurDualFilter::generate(SkiaGpuContext* context, const uin
116120

117121
// Use a variable number of blur passes depending on the radius. The non-integer part of this
118122
// calculation is used to mix the final pass into the second-last with an alpha blend.
119-
constexpr int kMaxSurfaces = 4;
120-
const float filterDepth =
121-
std::min(kMaxSurfaces - 1.0f, 1.0f + std::max(0.0f, log2f(radius * kInputScale)));
123+
constexpr int kMaxSurfaces = 3;
124+
const float filterDepth = std::min(kMaxSurfaces - 1.0f, radius * kInputScale / 2.5f);
122125
const int filterPasses = std::min(kMaxSurfaces - 1, static_cast<int>(ceil(filterDepth)));
123126

124-
// Render into surfaces downscaled by 1x, 1x, 2x, and 4x from the initial downscale.
127+
// Render into surfaces downscaled by 1x, 2x, and 4x from the initial downscale.
125128
sk_sp<SkSurface> surfaces[kMaxSurfaces] =
126129
{filterPasses >= 0 ? makeSurface(context, blurRect, 1 * kInverseInputScale) : nullptr,
127-
filterPasses >= 1 ? makeSurface(context, blurRect, 1 * kInverseInputScale) : nullptr,
128-
filterPasses >= 2 ? makeSurface(context, blurRect, 2 * kInverseInputScale) : nullptr,
129-
filterPasses >= 3 ? makeSurface(context, blurRect, 4 * kInverseInputScale) : nullptr};
130-
131-
// These weights for scaling offsets per-pass are handpicked to look good at 1 <= radius <= 600.
132-
static const float kWeights[7] = {1.0f, 2.0f, 3.5f, 1.0f, 2.0f, 2.0f, 2.0f};
130+
filterPasses >= 1 ? makeSurface(context, blurRect, 2 * kInverseInputScale) : nullptr,
131+
filterPasses >= 2 ? makeSurface(context, blurRect, 4 * kInverseInputScale) : nullptr};
132+
133+
// These weights for scaling offsets per-pass are handpicked to look good at 1 <= radius <= 250.
134+
static const float kWeights[5] = {
135+
1.0f, // 1st downsampling pass
136+
1.0f, // 2nd downsampling pass
137+
1.0f, // 3rd downsampling pass
138+
0.0f, // 1st upscaling pass. Set to zero to upscale without blurring for performance.
139+
1.0f, // 2nd upscaling pass
140+
};
133141

134142
// Kawase is an approximation of Gaussian, but behaves differently because it is made up of many
135143
// simpler blurs. A transformation is required to approximate the same effect as Gaussian.
136-
float sumSquaredR = powf(kWeights[0] * powf(2.0f, 1), 2.0f);
144+
float sumSquaredR = powf(kWeights[0], 2.0f);
137145
for (int i = 0; i < filterPasses; i++) {
138146
const float alpha = std::min(1.0f, filterDepth - i);
139-
sumSquaredR += powf(powf(2.0f, i + 1) * alpha * kWeights[1 + i], 2.0f);
140-
sumSquaredR += powf(powf(2.0f, i + 1) * alpha * kWeights[6 - i], 2.0f);
147+
sumSquaredR += powf(powf(2.0f, i) * alpha * kWeights[1 + i] / kInputScale, 2.0f);
148+
sumSquaredR += powf(powf(2.0f, i + 1) * alpha * kWeights[4 - i] / kInputScale, 2.0f);
141149
}
142-
// Solve for R = sqrt(sum(r_i^2)). Divide R by hypot(1,1) to find some (x,y) offsets.
143-
const float step = M_SQRT1_2 *
144-
sqrtf(max(0.0f, (powf(radius, 2.0f) - powf(kInverseInputScale, 2.0f)) / sumSquaredR));
150+
// Solve for R = sqrt(sum(r_i^2)).
151+
const float step = radius * sqrt(1.0f / sumSquaredR);
145152

146153
// Start by downscaling and doing the first blur pass.
147154
{
@@ -162,7 +169,7 @@ sk_sp<SkImage> KawaseBlurDualFilter::generate(SkiaGpuContext* context, const uin
162169
}
163170
// Finally blur+upscale back to our original size.
164171
for (int i = filterPasses - 1; i >= 0; i--) {
165-
blurInto(surfaces[i], surfaces[i + 1]->makeImageSnapshot(), kWeights[6 - i] * step,
172+
blurInto(surfaces[i], surfaces[i + 1]->makeImageSnapshot(), kWeights[4 - i] * step,
166173
std::min(1.0f, filterDepth - i));
167174
}
168175
return surfaces[0]->makeImageSnapshot();

0 commit comments

Comments
 (0)