Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 0166141

Browse files
[Impeller] Fix 1d threadgroup dispatch size, Implement drawPoint geometry computation with compute, fallback to specialized CPU. (#42060)
Compute shader implementation of #41803 I found this to be generally more straightforward, and we can revisit the vertex shader approach with GLES. Benchmark is pending here: flutter/flutter#126728 Note: rendering behavior is identical even though this is now a single draw call. This is becuase strokes have overdraw prevention enabled by default, while this new contents does not ![image](https://github.com/flutter/engine/assets/8975114/29d84e0d-7be6-426a-b5e3-5226c1953a47)
1 parent 2b14f8a commit 0166141

18 files changed

+540
-28
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,6 +1295,7 @@ ORIGIN: ../../../flutter/impeller/entity/shaders/gaussian_blur/gaussian_blur_alp
12951295
ORIGIN: ../../../flutter/impeller/entity/shaders/gaussian_blur/gaussian_blur_alpha_nodecal.frag + ../../../flutter/LICENSE
12961296
ORIGIN: ../../../flutter/impeller/entity/shaders/gaussian_blur/gaussian_blur_noalpha_decal.frag + ../../../flutter/LICENSE
12971297
ORIGIN: ../../../flutter/impeller/entity/shaders/gaussian_blur/gaussian_blur_noalpha_nodecal.frag + ../../../flutter/LICENSE
1298+
ORIGIN: ../../../flutter/impeller/entity/shaders/geometry/points.comp + ../../../flutter/LICENSE
12981299
ORIGIN: ../../../flutter/impeller/entity/shaders/glyph_atlas.frag + ../../../flutter/LICENSE
12991300
ORIGIN: ../../../flutter/impeller/entity/shaders/glyph_atlas.vert + ../../../flutter/LICENSE
13001301
ORIGIN: ../../../flutter/impeller/entity/shaders/glyph_atlas_color.frag + ../../../flutter/LICENSE
@@ -3916,6 +3917,7 @@ FILE: ../../../flutter/impeller/entity/shaders/gaussian_blur/gaussian_blur_alpha
39163917
FILE: ../../../flutter/impeller/entity/shaders/gaussian_blur/gaussian_blur_alpha_nodecal.frag
39173918
FILE: ../../../flutter/impeller/entity/shaders/gaussian_blur/gaussian_blur_noalpha_decal.frag
39183919
FILE: ../../../flutter/impeller/entity/shaders/gaussian_blur/gaussian_blur_noalpha_nodecal.frag
3920+
FILE: ../../../flutter/impeller/entity/shaders/geometry/points.comp
39193921
FILE: ../../../flutter/impeller/entity/shaders/glyph_atlas.frag
39203922
FILE: ../../../flutter/impeller/entity/shaders/glyph_atlas.vert
39213923
FILE: ../../../flutter/impeller/entity/shaders/glyph_atlas_color.frag

impeller/aiks/aiks_unittests.cc

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2320,5 +2320,35 @@ TEST_P(AiksTest, CanRenderClippedRuntimeEffects) {
23202320
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
23212321
}
23222322

2323+
TEST_P(AiksTest, CanDrawPoints) {
2324+
std::vector<Point> points = {
2325+
{0, 0}, //
2326+
{100, 100}, //
2327+
{100, 0}, //
2328+
{0, 100}, //
2329+
{0, 0}, //
2330+
{48, 48}, //
2331+
{52, 52}, //
2332+
};
2333+
std::vector<PointStyle> caps = {
2334+
PointStyle::kRound,
2335+
PointStyle::kSquare,
2336+
};
2337+
Paint paint;
2338+
paint.color = Color::Yellow().WithAlpha(0.5);
2339+
2340+
Paint background;
2341+
background.color = Color::Black();
2342+
2343+
Canvas canvas;
2344+
canvas.DrawPaint(background);
2345+
canvas.Translate({200, 200});
2346+
canvas.DrawPoints(points, 10, paint, PointStyle::kRound);
2347+
canvas.Translate({150, 0});
2348+
canvas.DrawPoints(points, 10, paint, PointStyle::kSquare);
2349+
2350+
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2351+
}
2352+
23232353
} // namespace testing
23242354
} // namespace impeller

impeller/aiks/canvas.cc

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,25 @@ void Canvas::RestoreClip() {
383383
GetCurrentPass().AddEntity(entity);
384384
}
385385

386+
void Canvas::DrawPoints(std::vector<Point> points,
387+
Scalar radius,
388+
const Paint& paint,
389+
PointStyle point_style) {
390+
if (radius <= 0) {
391+
return;
392+
}
393+
394+
Entity entity;
395+
entity.SetTransformation(GetCurrentTransformation());
396+
entity.SetStencilDepth(GetStencilDepth());
397+
entity.SetBlendMode(paint.blend_mode);
398+
entity.SetContents(paint.WithFilters(paint.CreateContentsForGeometry(
399+
Geometry::MakePointField(std::move(points), radius,
400+
/*round=*/point_style == PointStyle::kRound))));
401+
402+
GetCurrentPass().AddEntity(entity);
403+
}
404+
386405
void Canvas::DrawPicture(Picture picture) {
387406
if (!picture.pass) {
388407
return;

impeller/aiks/canvas.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ struct CanvasStackEntry {
3737
bool contains_clips = false;
3838
};
3939

40+
enum class PointStyle {
41+
/// @brief Points are drawn as squares.
42+
kRound,
43+
44+
/// @brief Points are drawn as circles.
45+
kSquare,
46+
};
47+
4048
class Canvas {
4149
public:
4250
struct DebugOptions {
@@ -100,6 +108,11 @@ class Canvas {
100108

101109
void DrawCircle(Point center, Scalar radius, const Paint& paint);
102110

111+
void DrawPoints(std::vector<Point>,
112+
Scalar radius,
113+
const Paint& paint,
114+
PointStyle point_style);
115+
103116
void DrawImage(const std::shared_ptr<Image>& image,
104117
Point offset,
105118
const Paint& paint,

impeller/display_list/dl_dispatcher.cc

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -930,16 +930,17 @@ void DlDispatcher::drawPoints(PointMode mode,
930930
Paint paint = paint_;
931931
paint.style = Paint::Style::kStroke;
932932
switch (mode) {
933-
case flutter::DlCanvas::PointMode::kPoints:
934-
if (paint.stroke_cap == Cap::kButt) {
935-
paint.stroke_cap = Cap::kSquare;
933+
case flutter::DlCanvas::PointMode::kPoints: {
934+
// Cap::kButt is also treated as a square.
935+
auto point_style = paint.stroke_cap == Cap::kRound ? PointStyle::kRound
936+
: PointStyle::kSquare;
937+
auto radius = paint.stroke_width;
938+
if (radius > 0) {
939+
radius /= 2.0;
936940
}
937-
for (uint32_t i = 0; i < count; i++) {
938-
Point p0 = skia_conversions::ToPoint(points[i]);
939-
auto path = PathBuilder{}.AddLine(p0, p0).TakePath();
940-
canvas_.DrawPath(path, paint);
941-
}
942-
break;
941+
canvas_.DrawPoints(skia_conversions::ToPoints(points, count), radius,
942+
paint, point_style);
943+
} break;
943944
case flutter::DlCanvas::PointMode::kLines:
944945
for (uint32_t i = 1; i < count; i += 2) {
945946
Point p0 = skia_conversions::ToPoint(points[i - 1]);

impeller/display_list/skia_conversions.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ std::vector<Rect> ToRects(const SkRect tex[], int count) {
2626
return result;
2727
}
2828

29+
std::vector<Point> ToPoints(const SkPoint points[], int count) {
30+
std::vector<Point> result(count);
31+
for (auto i = 0; i < count; i++) {
32+
result[i] = ToPoint(points[i]);
33+
}
34+
return result;
35+
}
36+
2937
PathBuilder::RoundingRadii ToRoundingRadii(const SkRRect& rrect) {
3038
using Corner = SkRRect::Corner;
3139
PathBuilder::RoundingRadii radii;

impeller/display_list/skia_conversions.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ std::optional<Rect> ToRect(const SkRect* rect);
2626

2727
std::vector<Rect> ToRects(const SkRect tex[], int count);
2828

29+
std::vector<Point> ToPoints(const SkPoint points[], int count);
30+
2931
Point ToPoint(const SkPoint& point);
3032

3133
Color ToColor(const SkColor& color);

impeller/entity/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ impeller_shaders("modern_entity_shaders") {
9696
"shaders/linear_gradient_ssbo_fill.frag",
9797
"shaders/radial_gradient_ssbo_fill.frag",
9898
"shaders/sweep_gradient_ssbo_fill.frag",
99+
"shaders/geometry/points.comp",
99100
]
100101
}
101102

impeller/entity/contents/content_context.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "impeller/core/formats.h"
1212
#include "impeller/entity/entity.h"
1313
#include "impeller/renderer/command_buffer.h"
14+
#include "impeller/renderer/pipeline_library.h"
1415
#include "impeller/renderer/render_pass.h"
1516
#include "impeller/renderer/render_target.h"
1617
#include "impeller/tessellator/tessellator.h"
@@ -296,6 +297,13 @@ ContentContext::ContentContext(std::shared_ptr<Context> context)
296297
porter_duff_blend_pipelines_[{}] =
297298
CreateDefaultPipeline<PorterDuffBlendPipeline>(*context_);
298299

300+
if (context_->GetCapabilities()->SupportsCompute()) {
301+
auto pipeline_desc =
302+
PointsComputeShaderPipeline::MakeDefaultPipelineDescriptor(*context_);
303+
point_field_compute_pipelines_ =
304+
context_->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
305+
}
306+
299307
if (solid_fill_pipelines_[{}]->GetDescriptor().has_value()) {
300308
auto clip_pipeline_descriptor =
301309
solid_fill_pipelines_[{}]->GetDescriptor().value();

impeller/entity/contents/content_context.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "impeller/entity/linear_to_srgb_filter.vert.h"
4040
#include "impeller/entity/morphology_filter.frag.h"
4141
#include "impeller/entity/morphology_filter.vert.h"
42+
#include "impeller/entity/points.comp.h"
4243
#include "impeller/entity/porter_duff_blend.frag.h"
4344
#include "impeller/entity/radial_gradient_fill.frag.h"
4445
#include "impeller/entity/rrect_blur.frag.h"
@@ -275,6 +276,9 @@ using FramebufferBlendSoftLightPipeline =
275276
RenderPipelineT<FramebufferBlendVertexShader,
276277
FramebufferBlendSoftlightFragmentShader>;
277278

279+
/// Geometry Pipelines
280+
using PointsComputeShaderPipeline = ComputePipelineBuilder<PointsComputeShader>;
281+
278282
/// Pipeline state configuration.
279283
///
280284
/// Each unique combination of these options requires a different pipeline state
@@ -660,6 +664,12 @@ class ContentContext {
660664
return GetPipeline(framebuffer_blend_softlight_pipelines_, opts);
661665
}
662666

667+
std::shared_ptr<Pipeline<ComputePipelineDescriptor>> GetPointComputePipeline()
668+
const {
669+
FML_DCHECK(GetDeviceCapabilities().SupportsCompute());
670+
return point_field_compute_pipelines_;
671+
}
672+
663673
std::shared_ptr<Context> GetContext() const;
664674

665675
std::shared_ptr<GlyphAtlasContext> GetGlyphAtlasContext(
@@ -782,6 +792,8 @@ class ContentContext {
782792
framebuffer_blend_screen_pipelines_;
783793
mutable Variants<FramebufferBlendSoftLightPipeline>
784794
framebuffer_blend_softlight_pipelines_;
795+
mutable std::shared_ptr<Pipeline<ComputePipelineDescriptor>>
796+
point_field_compute_pipelines_;
785797

786798
template <class TypedPipeline>
787799
std::shared_ptr<Pipeline<PipelineDescriptor>> GetPipeline(

impeller/entity/entity_unittests.cc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2616,5 +2616,23 @@ TEST_P(EntityTest, TessellateConvex) {
26162616
}
26172617
}
26182618

2619+
TEST_P(EntityTest, PointFieldGeometryDivisions) {
2620+
// Square always gives 4 divisions.
2621+
ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(24.0, false), 4u);
2622+
ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(2.0, false), 4u);
2623+
ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(200.0, false), 4u);
2624+
2625+
ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(0.5, true), 4u);
2626+
ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(1.5, true), 8u);
2627+
ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(5.5, true), 24u);
2628+
ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(12.5, true), 34u);
2629+
ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(22.3, true), 22u);
2630+
ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(40.5, true), 40u);
2631+
ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(100.0, true), 100u);
2632+
// Caps at 140.
2633+
ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(1000.0, true), 140u);
2634+
ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(20000.0, true), 140u);
2635+
}
2636+
26192637
} // namespace testing
26202638
} // namespace impeller

0 commit comments

Comments
 (0)