44
55#include " impeller/entity/geometry/point_field_geometry.h"
66
7- #include " impeller/geometry/color.h"
7+ #include " impeller/core/vertex_buffer.h"
8+ #include " impeller/entity/geometry/geometry.h"
89#include " impeller/renderer/command_buffer.h"
910
1011namespace impeller {
@@ -18,38 +19,19 @@ GeometryResult PointFieldGeometry::GetPositionBuffer(
1819 const ContentContext& renderer,
1920 const Entity& entity,
2021 RenderPass& pass) const {
21- if (renderer.GetDeviceCapabilities ().SupportsCompute ()) {
22- return GetPositionBufferGPU (renderer, entity, pass);
23- }
24- auto vtx_builder = GetPositionBufferCPU (renderer, entity, pass);
25- if (!vtx_builder.has_value ()) {
26- return {};
27- }
28-
29- auto & host_buffer = renderer.GetTransientsBuffer ();
30- return {
31- .type = PrimitiveType::kTriangleStrip ,
32- .vertex_buffer = vtx_builder->CreateVertexBuffer (host_buffer),
33- .transform = entity.GetShaderTransform (pass),
34- };
35- }
36-
37- std::optional<VertexBufferBuilder<SolidFillVertexShader::PerVertexData>>
38- PointFieldGeometry::GetPositionBufferCPU (const ContentContext& renderer,
39- const Entity& entity,
40- RenderPass& pass) const {
4122 if (radius_ < 0.0 ) {
42- return std:: nullopt ;
23+ return {} ;
4324 }
44- auto transform = entity.GetTransform ();
45- auto determinant = transform.GetDeterminant ();
25+ Matrix transform = entity.GetTransform ();
26+ Scalar determinant = transform.GetDeterminant ();
4627 if (determinant == 0 ) {
47- return std:: nullopt ;
28+ return {} ;
4829 }
4930
5031 Scalar min_size = 1 .0f / sqrt (std::abs (determinant));
5132 Scalar radius = std::max (radius_, min_size);
5233
34+ HostBuffer& host_buffer = renderer.GetTransientsBuffer ();
5335 VertexBufferBuilder<SolidFillVertexShader::PerVertexData> vtx_builder;
5436
5537 if (round_) {
@@ -94,114 +76,13 @@ PointFieldGeometry::GetPositionBufferCPU(const ContentContext& renderer,
9476 }
9577 }
9678
97- return vtx_builder;
98- }
99-
100- GeometryResult PointFieldGeometry::GetPositionBufferGPU (
101- const ContentContext& renderer,
102- const Entity& entity,
103- RenderPass& pass) const {
104- FML_DCHECK (renderer.GetDeviceCapabilities ().SupportsCompute ());
105- if (radius_ < 0.0 ) {
106- return {};
107- }
108- Scalar determinant = entity.GetTransform ().GetDeterminant ();
109- if (determinant == 0 ) {
110- return {};
111- }
112-
113- Scalar min_size = 1 .0f / sqrt (std::abs (determinant));
114- Scalar radius = std::max (radius_, min_size);
115-
116- size_t vertices_per_geom = ComputeCircleDivisions (
117- entity.GetTransform ().GetMaxBasisLength () * radius, round_);
118-
119- size_t points_per_circle = 3 + (vertices_per_geom - 3 ) * 3 ;
120- size_t total = points_per_circle * points_.size ();
121-
122- std::shared_ptr<CommandBuffer> cmd_buffer =
123- renderer.GetContext ()->CreateCommandBuffer ();
124- std::shared_ptr<ComputePass> compute_pass = cmd_buffer->CreateComputePass ();
125- HostBuffer& host_buffer = renderer.GetTransientsBuffer ();
126-
127- BufferView points_data =
128- host_buffer.Emplace (points_.data (), points_.size () * sizeof (Point),
129- DefaultUniformAlignment ());
130-
131- BufferView geometry_buffer =
132- host_buffer.Emplace (nullptr , total * sizeof (Point),
133- std::max (DefaultUniformAlignment (), alignof (Point)));
134-
135- BufferView output;
136- {
137- using PS = PointsComputeShader;
138-
139- compute_pass->SetPipeline (renderer.GetPointComputePipeline ());
140- compute_pass->SetCommandLabel (" Points Geometry" );
141-
142- PS::FrameInfo frame_info;
143- frame_info.count = points_.size ();
144- frame_info.radius = round_ ? radius : radius * kSqrt2 ;
145- frame_info.radian_start = round_ ? 0 .0f : kPiOver4 ;
146- frame_info.radian_step = k2Pi / vertices_per_geom;
147- frame_info.points_per_circle = points_per_circle;
148- frame_info.divisions_per_circle = vertices_per_geom;
149-
150- PS::BindFrameInfo (*compute_pass, host_buffer.EmplaceUniform (frame_info));
151- PS::BindGeometryData (*compute_pass, geometry_buffer);
152- PS::BindPointData (*compute_pass, points_data);
153-
154- if (!compute_pass->Compute (ISize (total, 1 )).ok ()) {
155- return {};
156- }
157- output = geometry_buffer;
158- }
159-
160- if (!compute_pass->EncodeCommands ()) {
161- return {};
162- }
163- if (!renderer.GetContext ()
164- ->GetCommandQueue ()
165- ->Submit ({std::move (cmd_buffer)})
166- .ok ()) {
167- return {};
168- }
169-
170- return {
171- .type = PrimitiveType::kTriangle ,
172- .vertex_buffer = {.vertex_buffer = std::move (output),
173- .vertex_count = total,
174- .index_type = IndexType::kNone },
79+ return GeometryResult{
80+ .type = PrimitiveType::kTriangleStrip ,
81+ .vertex_buffer = vtx_builder.CreateVertexBuffer (host_buffer),
17582 .transform = entity.GetShaderTransform (pass),
17683 };
17784}
17885
179- // / @brief Compute the number of vertices to divide each circle into.
180- // /
181- // / @return the number of vertices.
182- size_t PointFieldGeometry::ComputeCircleDivisions (Scalar scaled_radius,
183- bool round) {
184- if (!round) {
185- return 4 ;
186- }
187-
188- // Note: these values are approximated based on the values returned from
189- // the decomposition of 4 cubics performed by Path::CreatePolyline.
190- if (scaled_radius < 1.0 ) {
191- return 4 ;
192- }
193- if (scaled_radius < 2.0 ) {
194- return 8 ;
195- }
196- if (scaled_radius < 12.0 ) {
197- return 24 ;
198- }
199- if (scaled_radius < 22.0 ) {
200- return 34 ;
201- }
202- return std::min (scaled_radius, 140 .0f );
203- }
204-
20586// |Geometry|
20687std::optional<Rect> PointFieldGeometry::GetCoverage (
20788 const Matrix& transform) const {
0 commit comments