Skip to content

Commit

Permalink
[Impeller] delete points compute shader. (#52346)
Browse files Browse the repository at this point in the history
We only use this for drawPoints, a rarely used API. On local tests, this is just as fast with the CPU backend implementations.

While this was intended to be the first in a series of compute based rendering experiments, it hasn't really been worth the carrying cost. So lets shrink the complexity and and remove another shader to boot.

Fixes flutter/flutter#147184
  • Loading branch information
jonahwilliams authored Apr 24, 2024
1 parent c330ca8 commit 88fc864
Show file tree
Hide file tree
Showing 11 changed files with 12 additions and 317 deletions.
2 changes: 0 additions & 2 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -40396,7 +40396,6 @@ ORIGIN: ../../../flutter/impeller/entity/shaders/gaussian_blur/kernel.glsl + ../
ORIGIN: ../../../flutter/impeller/entity/shaders/gaussian_blur/kernel.vert + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/entity/shaders/gaussian_blur/kernel_decal.frag + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/entity/shaders/gaussian_blur/kernel_nodecal.frag + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/entity/shaders/geometry/points.comp + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/entity/shaders/glyph_atlas.frag + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/entity/shaders/glyph_atlas.vert + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/entity/shaders/glyph_atlas_color.frag + ../../../flutter/LICENSE
Expand Down Expand Up @@ -43278,7 +43277,6 @@ FILE: ../../../flutter/impeller/entity/shaders/gaussian_blur/kernel.glsl
FILE: ../../../flutter/impeller/entity/shaders/gaussian_blur/kernel.vert
FILE: ../../../flutter/impeller/entity/shaders/gaussian_blur/kernel_decal.frag
FILE: ../../../flutter/impeller/entity/shaders/gaussian_blur/kernel_nodecal.frag
FILE: ../../../flutter/impeller/entity/shaders/geometry/points.comp
FILE: ../../../flutter/impeller/entity/shaders/glyph_atlas.frag
FILE: ../../../flutter/impeller/entity/shaders/glyph_atlas.vert
FILE: ../../../flutter/impeller/entity/shaders/glyph_atlas_color.frag
Expand Down
8 changes: 0 additions & 8 deletions impeller/aiks/aiks_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2349,10 +2349,6 @@ TEST_P(AiksTest, DrawPaintTransformsBounds) {
}

TEST_P(AiksTest, CanDrawPoints) {
if (GetBackend() == PlaygroundBackend::kMetal) {
// https://github.com/flutter/flutter/issues/147184
GTEST_SKIP() << "Draw Points is currently broken on the metal m1 backend.";
}
std::vector<Point> points = {
{0, 0}, //
{100, 100}, //
Expand Down Expand Up @@ -2447,10 +2443,6 @@ TEST_P(AiksTest, DrawAtlasAdvancedAndTransform) {
}

TEST_P(AiksTest, CanDrawPointsWithTextureMap) {
if (GetBackend() == PlaygroundBackend::kMetal) {
// https://github.com/flutter/flutter/issues/147184
GTEST_SKIP() << "Draw Points is currently broken on the metal m1 backend.";
}
auto texture = CreateTextureForFixture("table_mountain_nx.png",
/*enable_mipmapping=*/true);

Expand Down
1 change: 0 additions & 1 deletion impeller/entity/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ impeller_shaders("modern_entity_shaders") {
"shaders/gradients/linear_gradient_ssbo_fill.frag",
"shaders/gradients/radial_gradient_ssbo_fill.frag",
"shaders/gradients/sweep_gradient_ssbo_fill.frag",
"shaders/geometry/points.comp",
]
}

Expand Down
6 changes: 0 additions & 6 deletions impeller/entity/contents/content_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -450,12 +450,6 @@ ContentContext::ContentContext(
tiled_texture_external_pipelines_.CreateDefault(*context_, options);
}
#endif // IMPELLER_ENABLE_OPENGLES
if (context_->GetCapabilities()->SupportsCompute()) {
auto pipeline_desc =
PointsComputeShaderPipeline::MakeDefaultPipelineDescriptor(*context_);
point_field_compute_pipelines_ =
context_->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
}

is_valid_ = true;
InitializeCommonlyUsedShadersIfNeeded();
Expand Down
12 changes: 0 additions & 12 deletions impeller/entity/contents/content_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
#include "impeller/entity/linear_to_srgb_filter.frag.h"
#include "impeller/entity/morphology_filter.frag.h"
#include "impeller/entity/morphology_filter.vert.h"
#include "impeller/entity/points.comp.h"
#include "impeller/entity/porter_duff_blend.frag.h"
#include "impeller/entity/porter_duff_blend.vert.h"
#include "impeller/entity/radial_gradient_fill.frag.h"
Expand Down Expand Up @@ -256,9 +255,6 @@ using FramebufferBlendSoftLightPipeline =
using VerticesUberShader =
RenderPipelineHandle<VerticesUberVertexShader, VerticesUberFragmentShader>;

/// Geometry Pipelines
using PointsComputeShaderPipeline = ComputePipelineBuilder<PointsComputeShader>;

#ifdef IMPELLER_ENABLE_OPENGLES
using TiledTextureExternalPipeline =
RenderPipelineHandle<TextureUvFillVertexShader,
Expand Down Expand Up @@ -719,12 +715,6 @@ class ContentContext {
return GetPipeline(vertices_uber_shader_, opts);
}

std::shared_ptr<Pipeline<ComputePipelineDescriptor>> GetPointComputePipeline()
const {
FML_DCHECK(GetDeviceCapabilities().SupportsCompute());
return point_field_compute_pipelines_;
}

std::shared_ptr<Context> GetContext() const;

const Capabilities& GetDeviceCapabilities() const;
Expand Down Expand Up @@ -987,8 +977,6 @@ class ContentContext {
mutable Variants<FramebufferBlendSoftLightPipeline>
framebuffer_blend_softlight_pipelines_;
mutable Variants<VerticesUberShader> vertices_uber_shader_;
mutable std::shared_ptr<Pipeline<ComputePipelineDescriptor>>
point_field_compute_pipelines_;

template <class TypedPipeline>
std::shared_ptr<Pipeline<PipelineDescriptor>> GetPipeline(
Expand Down
18 changes: 0 additions & 18 deletions impeller/entity/entity_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2519,24 +2519,6 @@ TEST_P(EntityTest, TiledTextureContentsIsOpaque) {
ASSERT_FALSE(contents.IsOpaque());
}

TEST_P(EntityTest, PointFieldGeometryDivisions) {
// Square always gives 4 divisions.
ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(24.0, false), 4u);
ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(2.0, false), 4u);
ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(200.0, false), 4u);

ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(0.5, true), 4u);
ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(1.5, true), 8u);
ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(5.5, true), 24u);
ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(12.5, true), 34u);
ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(22.3, true), 22u);
ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(40.5, true), 40u);
ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(100.0, true), 100u);
// Caps at 140.
ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(1000.0, true), 140u);
ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(20000.0, true), 140u);
}

TEST_P(EntityTest, PointFieldGeometryCoverage) {
std::vector<Point> points = {{10, 20}, {100, 200}};
auto geometry = Geometry::MakePointField(points, 5.0, false);
Expand Down
139 changes: 10 additions & 129 deletions impeller/entity/geometry/point_field_geometry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

#include "impeller/entity/geometry/point_field_geometry.h"

#include "impeller/geometry/color.h"
#include "impeller/core/vertex_buffer.h"
#include "impeller/entity/geometry/geometry.h"
#include "impeller/renderer/command_buffer.h"

namespace impeller {
Expand All @@ -18,38 +19,19 @@ GeometryResult PointFieldGeometry::GetPositionBuffer(
const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const {
if (renderer.GetDeviceCapabilities().SupportsCompute()) {
return GetPositionBufferGPU(renderer, entity, pass);
}
auto vtx_builder = GetPositionBufferCPU(renderer, entity, pass);
if (!vtx_builder.has_value()) {
return {};
}

auto& host_buffer = renderer.GetTransientsBuffer();
return {
.type = PrimitiveType::kTriangleStrip,
.vertex_buffer = vtx_builder->CreateVertexBuffer(host_buffer),
.transform = entity.GetShaderTransform(pass),
};
}

std::optional<VertexBufferBuilder<SolidFillVertexShader::PerVertexData>>
PointFieldGeometry::GetPositionBufferCPU(const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const {
if (radius_ < 0.0) {
return std::nullopt;
return {};
}
auto transform = entity.GetTransform();
auto determinant = transform.GetDeterminant();
Matrix transform = entity.GetTransform();
Scalar determinant = transform.GetDeterminant();
if (determinant == 0) {
return std::nullopt;
return {};
}

Scalar min_size = 1.0f / sqrt(std::abs(determinant));
Scalar radius = std::max(radius_, min_size);

HostBuffer& host_buffer = renderer.GetTransientsBuffer();
VertexBufferBuilder<SolidFillVertexShader::PerVertexData> vtx_builder;

if (round_) {
Expand Down Expand Up @@ -94,114 +76,13 @@ PointFieldGeometry::GetPositionBufferCPU(const ContentContext& renderer,
}
}

return vtx_builder;
}

GeometryResult PointFieldGeometry::GetPositionBufferGPU(
const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const {
FML_DCHECK(renderer.GetDeviceCapabilities().SupportsCompute());
if (radius_ < 0.0) {
return {};
}
Scalar determinant = entity.GetTransform().GetDeterminant();
if (determinant == 0) {
return {};
}

Scalar min_size = 1.0f / sqrt(std::abs(determinant));
Scalar radius = std::max(radius_, min_size);

size_t vertices_per_geom = ComputeCircleDivisions(
entity.GetTransform().GetMaxBasisLength() * radius, round_);

size_t points_per_circle = 3 + (vertices_per_geom - 3) * 3;
size_t total = points_per_circle * points_.size();

std::shared_ptr<CommandBuffer> cmd_buffer =
renderer.GetContext()->CreateCommandBuffer();
std::shared_ptr<ComputePass> compute_pass = cmd_buffer->CreateComputePass();
HostBuffer& host_buffer = renderer.GetTransientsBuffer();

BufferView points_data =
host_buffer.Emplace(points_.data(), points_.size() * sizeof(Point),
DefaultUniformAlignment());

BufferView geometry_buffer =
host_buffer.Emplace(nullptr, total * sizeof(Point),
std::max(DefaultUniformAlignment(), alignof(Point)));

BufferView output;
{
using PS = PointsComputeShader;

compute_pass->SetPipeline(renderer.GetPointComputePipeline());
compute_pass->SetCommandLabel("Points Geometry");

PS::FrameInfo frame_info;
frame_info.count = points_.size();
frame_info.radius = round_ ? radius : radius * kSqrt2;
frame_info.radian_start = round_ ? 0.0f : kPiOver4;
frame_info.radian_step = k2Pi / vertices_per_geom;
frame_info.points_per_circle = points_per_circle;
frame_info.divisions_per_circle = vertices_per_geom;

PS::BindFrameInfo(*compute_pass, host_buffer.EmplaceUniform(frame_info));
PS::BindGeometryData(*compute_pass, geometry_buffer);
PS::BindPointData(*compute_pass, points_data);

if (!compute_pass->Compute(ISize(total, 1)).ok()) {
return {};
}
output = geometry_buffer;
}

if (!compute_pass->EncodeCommands()) {
return {};
}
if (!renderer.GetContext()
->GetCommandQueue()
->Submit({std::move(cmd_buffer)})
.ok()) {
return {};
}

return {
.type = PrimitiveType::kTriangle,
.vertex_buffer = {.vertex_buffer = std::move(output),
.vertex_count = total,
.index_type = IndexType::kNone},
return GeometryResult{
.type = PrimitiveType::kTriangleStrip,
.vertex_buffer = vtx_builder.CreateVertexBuffer(host_buffer),
.transform = entity.GetShaderTransform(pass),
};
}

/// @brief Compute the number of vertices to divide each circle into.
///
/// @return the number of vertices.
size_t PointFieldGeometry::ComputeCircleDivisions(Scalar scaled_radius,
bool round) {
if (!round) {
return 4;
}

// Note: these values are approximated based on the values returned from
// the decomposition of 4 cubics performed by Path::CreatePolyline.
if (scaled_radius < 1.0) {
return 4;
}
if (scaled_radius < 2.0) {
return 8;
}
if (scaled_radius < 12.0) {
return 24;
}
if (scaled_radius < 22.0) {
return 34;
}
return std::min(scaled_radius, 140.0f);
}

// |Geometry|
std::optional<Rect> PointFieldGeometry::GetCoverage(
const Matrix& transform) const {
Expand Down
11 changes: 0 additions & 11 deletions impeller/entity/geometry/point_field_geometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ class PointFieldGeometry final : public Geometry {

~PointFieldGeometry() = default;

static size_t ComputeCircleDivisions(Scalar scaled_radius, bool round);

private:
// |Geometry|
GeometryResult GetPositionBuffer(const ContentContext& renderer,
Expand All @@ -26,15 +24,6 @@ class PointFieldGeometry final : public Geometry {
// |Geometry|
std::optional<Rect> GetCoverage(const Matrix& transform) const override;

GeometryResult GetPositionBufferGPU(const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const;

std::optional<VertexBufferBuilder<SolidFillVertexShader::PerVertexData>>
GetPositionBufferCPU(const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const;

std::vector<Point> points_;
Scalar radius_;
bool round_;
Expand Down
67 changes: 0 additions & 67 deletions impeller/entity/shaders/geometry/points.comp

This file was deleted.

Loading

0 comments on commit 88fc864

Please sign in to comment.