-
Notifications
You must be signed in to change notification settings - Fork 6k
[Impeller] Fix GLES gaussian implementation. #55329
Changes from 4 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -325,7 +325,7 @@ DownsamplePassArgs CalculateDownsamplePassArgs( | |||||
fml::StatusOr<RenderTarget> MakeDownsampleSubpass( | ||||||
const ContentContext& renderer, | ||||||
const std::shared_ptr<CommandBuffer>& command_buffer, | ||||||
std::shared_ptr<Texture> input_texture, | ||||||
const std::shared_ptr<Texture>& input_texture, | ||||||
const SamplerDescriptor& sampler_descriptor, | ||||||
const DownsamplePassArgs& pass_args, | ||||||
Entity::TileMode tile_mode) { | ||||||
|
@@ -345,7 +345,8 @@ fml::StatusOr<RenderTarget> MakeDownsampleSubpass( | |||||
|
||||||
TextureFillVertexShader::FrameInfo frame_info; | ||||||
frame_info.mvp = Matrix::MakeOrthographic(ISize(1, 1)); | ||||||
frame_info.texture_sampler_y_coord_scale = 1.0; | ||||||
frame_info.texture_sampler_y_coord_scale = | ||||||
input_texture->GetYCoordScale(); | ||||||
|
||||||
TextureFillFragmentShader::FragInfo frag_info; | ||||||
frag_info.alpha = 1.0; | ||||||
|
@@ -398,7 +399,8 @@ fml::StatusOr<RenderTarget> MakeDownsampleSubpass( | |||||
|
||||||
TextureFillVertexShader::FrameInfo frame_info; | ||||||
frame_info.mvp = Matrix::MakeOrthographic(ISize(1, 1)); | ||||||
frame_info.texture_sampler_y_coord_scale = 1.0; | ||||||
frame_info.texture_sampler_y_coord_scale = | ||||||
input_texture->GetYCoordScale(); | ||||||
|
||||||
TextureDownsampleFragmentShader::FragInfo frag_info; | ||||||
frag_info.edge = edge; | ||||||
|
@@ -447,16 +449,18 @@ fml::StatusOr<RenderTarget> MakeBlurSubpass( | |||||
return input_pass; | ||||||
} | ||||||
|
||||||
std::shared_ptr<Texture> input_texture = input_pass.GetRenderTargetTexture(); | ||||||
const std::shared_ptr<Texture>& input_texture = | ||||||
input_pass.GetRenderTargetTexture(); | ||||||
|
||||||
// TODO(gaaclarke): This blurs the whole image, but because we know the clip | ||||||
// region we could focus on just blurring that. | ||||||
ISize subpass_size = input_texture->GetSize(); | ||||||
ContentContext::SubpassCallback subpass_callback = | ||||||
[&](const ContentContext& renderer, RenderPass& pass) { | ||||||
GaussianBlurVertexShader::FrameInfo frame_info{ | ||||||
.mvp = Matrix::MakeOrthographic(ISize(1, 1)), | ||||||
.texture_sampler_y_coord_scale = 1.0}; | ||||||
GaussianBlurVertexShader::FrameInfo frame_info; | ||||||
frame_info.mvp = Matrix::MakeOrthographic(ISize(1, 1)), | ||||||
frame_info.texture_sampler_y_coord_scale = | ||||||
input_texture->GetYCoordScale(); | ||||||
|
||||||
HostBuffer& host_buffer = renderer.GetTransientsBuffer(); | ||||||
|
||||||
|
@@ -481,11 +485,9 @@ fml::StatusOr<RenderTarget> MakeBlurSubpass( | |||||
linear_sampler_descriptor)); | ||||||
GaussianBlurVertexShader::BindFrameInfo( | ||||||
pass, host_buffer.EmplaceUniform(frame_info)); | ||||||
GaussianBlurPipeline::FragmentShader::KernelSamples kernel_samples = | ||||||
LerpHackKernelSamples(GenerateBlurInfo(blur_info)); | ||||||
FML_CHECK(kernel_samples.sample_count <= kGaussianBlurMaxKernelSize); | ||||||
GaussianBlurFragmentShader::BindKernelSamples( | ||||||
pass, host_buffer.EmplaceUniform(kernel_samples)); | ||||||
GaussianBlurFragmentShader::BindBlurInfo( | ||||||
pass, host_buffer.EmplaceUniform( | ||||||
LerpHackKernelSamples(GenerateBlurInfo(blur_info)))); | ||||||
return pass.Draw().ok(); | ||||||
}; | ||||||
if (destination_target.has_value()) { | ||||||
|
@@ -898,7 +900,7 @@ KernelSamples GenerateBlurInfo(BlurParameters parameters) { | |||||
Scalar tally = 0.0f; | ||||||
for (int i = 0; i < result.sample_count; ++i) { | ||||||
int x = x_offset + (i * parameters.step_size) - parameters.blur_radius; | ||||||
result.samples[i] = GaussianBlurPipeline::FragmentShader::KernelSample{ | ||||||
result.samples[i] = KernelSample{ | ||||||
.uv_offset = parameters.blur_uv_offset * x, | ||||||
.coefficient = expf(-0.5f * (x * x) / | ||||||
(parameters.blur_sigma * parameters.blur_sigma)) / | ||||||
|
@@ -917,27 +919,31 @@ KernelSamples GenerateBlurInfo(BlurParameters parameters) { | |||||
|
||||||
// This works by shrinking the kernel size by 2 and relying on lerp to read | ||||||
// between the samples. | ||||||
GaussianBlurPipeline::FragmentShader::KernelSamples LerpHackKernelSamples( | ||||||
GaussianBlurPipeline::FragmentShader::BlurInfo LerpHackKernelSamples( | ||||||
KernelSamples parameters) { | ||||||
GaussianBlurPipeline::FragmentShader::KernelSamples result; | ||||||
GaussianBlurPipeline::FragmentShader::BlurInfo result = {}; | ||||||
result.sample_count = ((parameters.sample_count - 1) / 2) + 1; | ||||||
int32_t middle = result.sample_count / 2; | ||||||
int32_t j = 0; | ||||||
FML_DCHECK(result.sample_count <= kGaussianBlurMaxKernelSize); | ||||||
|
||||||
for (int i = 0; i < result.sample_count; i++) { | ||||||
if (i == middle) { | ||||||
result.samples[i] = parameters.samples[j++]; | ||||||
result.sample_data[i].x = parameters.samples[j].uv_offset.x; | ||||||
result.sample_data[i].y = parameters.samples[j].uv_offset.y; | ||||||
result.sample_data[i].z = parameters.samples[j].coefficient; | ||||||
j++; | ||||||
} else { | ||||||
GaussianBlurPipeline::FragmentShader::KernelSample left = | ||||||
parameters.samples[j]; | ||||||
GaussianBlurPipeline::FragmentShader::KernelSample right = | ||||||
parameters.samples[j + 1]; | ||||||
result.samples[i] = GaussianBlurPipeline::FragmentShader::KernelSample{ | ||||||
.uv_offset = (left.uv_offset * left.coefficient + | ||||||
right.uv_offset * right.coefficient) / | ||||||
(left.coefficient + right.coefficient), | ||||||
.coefficient = left.coefficient + right.coefficient, | ||||||
}; | ||||||
KernelSample left = parameters.samples[j]; | ||||||
KernelSample right = parameters.samples[j + 1]; | ||||||
|
||||||
result.sample_data[i].z = left.coefficient + right.coefficient; | ||||||
|
||||||
auto uv = (left.uv_offset * left.coefficient + | ||||||
|
auto uv = (left.uv_offset * left.coefficient + | |
Point uv = (left.uv_offset * left.coefficient + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -508,27 +508,24 @@ TEST(GaussianBlurFilterContentsTest, LerpHackKernelSamplesSimple) { | |||||
}, | ||||||
}; | ||||||
|
||||||
GaussianBlurPipeline::FragmentShader::KernelSamples fast_kernel_samples = | ||||||
GaussianBlurPipeline::FragmentShader::BlurInfo blur_info = | ||||||
LerpHackKernelSamples(kernel_samples); | ||||||
EXPECT_EQ(fast_kernel_samples.sample_count, 3); | ||||||
EXPECT_EQ(blur_info.sample_count, 3); | ||||||
|
||||||
GaussianBlurPipeline::FragmentShader::KernelSample* samples = | ||||||
kernel_samples.samples; | ||||||
GaussianBlurPipeline::FragmentShader::KernelSample* fast_samples = | ||||||
fast_kernel_samples.samples; | ||||||
KernelSample* samples = kernel_samples.samples; | ||||||
|
||||||
////////////////////////////////////////////////////////////////////////////// | ||||||
// Check output kernel. | ||||||
|
||||||
EXPECT_FLOAT_EQ(fast_samples[0].uv_offset.x, -1.3333333); | ||||||
EXPECT_FLOAT_EQ(fast_samples[0].uv_offset.y, 0); | ||||||
EXPECT_FLOAT_EQ(fast_samples[0].coefficient, 0.3); | ||||||
EXPECT_FLOAT_EQ(fast_samples[1].uv_offset.x, 0); | ||||||
EXPECT_FLOAT_EQ(fast_samples[1].uv_offset.y, 0); | ||||||
EXPECT_FLOAT_EQ(fast_samples[1].coefficient, 0.4); | ||||||
EXPECT_FLOAT_EQ(fast_samples[2].uv_offset.x, 1.3333333); | ||||||
EXPECT_FLOAT_EQ(fast_samples[2].uv_offset.y, 0); | ||||||
EXPECT_FLOAT_EQ(fast_samples[2].coefficient, 0.3); | ||||||
EXPECT_FLOAT_EQ(blur_info.sample_data[0].x, -1.3333333); | ||||||
EXPECT_FLOAT_EQ(blur_info.sample_data[0].y, 0); | ||||||
EXPECT_FLOAT_EQ(blur_info.sample_data[0].z, 0.3); | ||||||
|
EXPECT_FLOAT_EQ(blur_info.sample_data[0].z, 0.3); | |
EXPECT_FLOAT_EQ(GetCoefficient(blur_info.sample_data[0]), 0.3); |
I think we would be better off not losing the names of values. It's very confusing to have to remember that .z
means "get the coefficient". Can we codify that into some tiny functions?
Same thing for uv_offset
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -57,6 +57,7 @@ class BufferBindingsGLES { | |
std::vector<VertexAttribPointer> vertex_attrib_arrays_; | ||
|
||
std::unordered_map<std::string, GLint> uniform_locations_; | ||
std::vector<uint8_t> array_element_buffer_; | ||
|
||
|
||
using BindingMap = std::unordered_map<std::string, std::vector<GLint>>; | ||
BindingMap binding_map_ = {}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please bring back this check. It's important because we'll crash anyways if we violate this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is checked in the LerpHackFunction too, I don't think the count can change after that point?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay yea, in that case I'd rather keep this one here since it is the final point before we'd actually get the error. We can remove the lerp hack one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But the kernel samples UBO has a std::array of a fixed size. It cannot be greater than kGaussianBlurMaxKernelSize
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could static assert this though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yea, the
sample_count
isn't even consequential here because emplace isn't looking at it. Lets keep the runtime DCHECK in the lerp hack and a static assert sounds good to me.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done