| Flutter Impeller |

compute_tessellator.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "impeller/renderer/compute_tessellator.h"
6
7 #include <cstdint>
8
9 #include "impeller/renderer/command_buffer.h"
10 #include "impeller/renderer/path_polyline.comp.h"
11 #include "impeller/renderer/pipeline_library.h"
12 #include "impeller/renderer/stroke.comp.h"
13
14 namespace impeller {
15
16 ComputeTessellator::ComputeTessellator() = default;
17 ComputeTessellator::~ComputeTessellator() = default;
18
19 template <typename T>
20 static std::shared_ptr<DeviceBuffer> CreateDeviceBuffer(
21 const std::shared_ptr<Context>& context,
22 const std::string& label,
23 StorageMode storage_mode = StorageMode::kDevicePrivate) {
24 DeviceBufferDescriptor desc;
25 desc.storage_mode = storage_mode;
26 desc.size = sizeof(T);
27 auto buffer = context->GetResourceAllocator()->CreateBuffer(desc);
28 buffer->SetLabel(label);
29 return buffer;
30 }
31
32 ComputeTessellator& ComputeTessellator::SetStyle(Style value) {
33 style_ = value;
34 return *this;
35 }
36
37 ComputeTessellator& ComputeTessellator::SetStrokeWidth(Scalar value) {
38 stroke_width_ = value;
39 return *this;
40 }
41
42 ComputeTessellator& ComputeTessellator::SetStrokeJoin(Join value) {
43 stroke_join_ = value;
44 return *this;
45 }
46 ComputeTessellator& ComputeTessellator::SetStrokeCap(Cap value) {
47 stroke_cap_ = value;
48 return *this;
49 }
50 ComputeTessellator& ComputeTessellator::SetMiterLimit(Scalar value) {
51 miter_limit_ = value;
52 return *this;
53 }
54 ComputeTessellator& ComputeTessellator::SetCubicAccuracy(Scalar value) {
55 cubic_accuracy_ = value;
56 return *this;
57 }
58 ComputeTessellator& ComputeTessellator::SetQuadraticTolerance(Scalar value) {
59 quad_tolerance_ = value;
60 return *this;
61 }
62
63 ComputeTessellator::Status ComputeTessellator::Tessellate(
64 const Path& path,
65 const std::shared_ptr<Context>& context,
66 BufferView vertex_buffer,
67 BufferView vertex_buffer_count,
68 const CommandBuffer::CompletionCallback& callback) const {
69 FML_DCHECK(style_ == Style::kStroke);
70 using PS = PathPolylineComputeShader;
71 using SS = StrokeComputeShader;
72
73 auto cubic_count = path.GetComponentCount(Path::ComponentType::kCubic);
74 auto quad_count = path.GetComponentCount(Path::ComponentType::kQuadratic) +
75 (cubic_count * 6);
76 auto line_count =
77 path.GetComponentCount(Path::ComponentType::kLinear) + (quad_count * 6);
78 if (cubic_count > kMaxCubicCount || quad_count > kMaxQuadCount ||
79 line_count > kMaxLineCount) {
80 return Status::kTooManyComponents;
81 }
82 PS::Cubics<kMaxCubicCount> cubics{.count = 0};
83 PS::Quads<kMaxQuadCount> quads{.count = 0};
84 PS::Lines<kMaxLineCount> lines{.count = 0};
85 PS::Components<kMaxComponentCount> components{.count = 0};
86 PS::Config config{.cubic_accuracy = cubic_accuracy_,
87 .quad_tolerance = quad_tolerance_};
88
89 path.EnumerateComponents(
90 [&lines, &components](size_t index, const LinearPathComponent& linear) {
91 ::memcpy(&lines.data[lines.count], &linear,
92 sizeof(LinearPathComponent));
93 components.data[components.count++] = {lines.count++, 2};
94 },
95 [&quads, &components](size_t index, const QuadraticPathComponent& quad) {
96 ::memcpy(&quads.data[quads.count], &quad,
97 sizeof(QuadraticPathComponent));
98 components.data[components.count++] = {quads.count++, 3};
99 },
100 [&cubics, &components](size_t index, const CubicPathComponent& cubic) {
101 ::memcpy(&cubics.data[cubics.count], &cubic,
102 sizeof(CubicPathComponent));
103 components.data[components.count++] = {cubics.count++, 4};
104 },
105 [](size_t index, const ContourComponent& contour) {});
106
107 auto polyline_buffer =
108 CreateDeviceBuffer<PS::Polyline<2048>>(context, "Polyline");
109
110 auto cmd_buffer = context->CreateCommandBuffer();
111 auto pass = cmd_buffer->CreateComputePass();
112 FML_DCHECK(pass && pass->IsValid());
113
114 {
115 using PathPolylinePipelineBuilder = ComputePipelineBuilder<PS>;
116 auto pipeline_desc =
117 PathPolylinePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
118 FML_DCHECK(pipeline_desc.has_value());
119 auto compute_pipeline =
120 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
121 FML_DCHECK(compute_pipeline);
122
123 pass->SetGridSize(ISize(line_count, 1));
124 pass->SetThreadGroupSize(ISize(line_count, 1));
125
126 ComputeCommand cmd;
127 DEBUG_COMMAND_INFO(cmd, "Generate Polyline");
128 cmd.pipeline = compute_pipeline;
129
130 PS::BindConfig(cmd, pass->GetTransientsBuffer().EmplaceUniform(config));
131 PS::BindCubics(cmd,
132 pass->GetTransientsBuffer().EmplaceStorageBuffer(cubics));
133 PS::BindQuads(cmd, pass->GetTransientsBuffer().EmplaceStorageBuffer(quads));
134 PS::BindLines(cmd, pass->GetTransientsBuffer().EmplaceStorageBuffer(lines));
135 PS::BindComponents(
136 cmd, pass->GetTransientsBuffer().EmplaceStorageBuffer(components));
137 PS::BindPolyline(cmd, polyline_buffer->AsBufferView());
138
139 if (!pass->AddCommand(std::move(cmd))) {
140 return Status::kCommandInvalid;
141 }
142 }
143
144 {
145 using StrokePipelineBuilder = ComputePipelineBuilder<SS>;
146 auto pipeline_desc =
147 StrokePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
148 FML_DCHECK(pipeline_desc.has_value());
149 auto compute_pipeline =
150 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
151 FML_DCHECK(compute_pipeline);
152
153 pass->SetGridSize(ISize(line_count, 1));
154 pass->SetThreadGroupSize(ISize(line_count, 1));
155
156 ComputeCommand cmd;
157 DEBUG_COMMAND_INFO(cmd, "Compute Stroke");
158 cmd.pipeline = compute_pipeline;
159
160 SS::Config config{
161 .width = stroke_width_,
162 .cap = static_cast<uint32_t>(stroke_cap_),
163 .join = static_cast<uint32_t>(stroke_join_),
164 .miter_limit = miter_limit_,
165 };
166 SS::BindConfig(cmd, pass->GetTransientsBuffer().EmplaceUniform(config));
167
168 SS::BindPolyline(cmd, polyline_buffer->AsBufferView());
169 SS::BindVertexBufferCount(cmd, std::move(vertex_buffer_count));
170 SS::BindVertexBuffer(cmd, std::move(vertex_buffer));
171
172 if (!pass->AddCommand(std::move(cmd))) {
173 return Status::kCommandInvalid;
174 }
175 }
176
177 if (!pass->EncodeCommands()) {
178 return Status::kCommandInvalid;
179 }
180
181 if (!cmd_buffer->SubmitCommands(callback)) {
182 return Status::kCommandInvalid;
183 }
184
185 return Status::kOk;
186 }
187
188 } // namespace impeller
impeller::ComputeTessellator::Status::kCommandInvalid
@ kCommandInvalid
DEBUG_COMMAND_INFO
#define DEBUG_COMMAND_INFO(obj, arg)
Definition: command.h:28
impeller::LinearPathComponent
Definition: path_component.h:28
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::ComputeTessellator::Status::kTooManyComponents
@ kTooManyComponents
impeller::Path::ComponentType::kLinear
@ kLinear
impeller::DeviceBufferDescriptor
Definition: device_buffer_descriptor.h:14
impeller::ComputeTessellator::Status
Status
Definition: compute_tessellator.h:32
impeller::ComputeCommand::pipeline
std::shared_ptr< Pipeline< ComputePipelineDescriptor > > pipeline
Definition: compute_command.h:40
impeller::Path::ComponentType::kCubic
@ kCubic
impeller::ComputeTessellator::SetStrokeCap
ComputeTessellator & SetStrokeCap(Cap value)
Definition: compute_tessellator.cc:46
impeller::Path::ComponentType::kQuadratic
@ kQuadratic
impeller::DeviceBufferDescriptor::size
size_t size
Definition: device_buffer_descriptor.h:16
impeller::ComputeTessellator::SetQuadraticTolerance
ComputeTessellator & SetQuadraticTolerance(Scalar value)
Definition: compute_tessellator.cc:58
compute_tessellator.h
impeller::ComputeTessellator::kMaxCubicCount
static constexpr size_t kMaxCubicCount
Definition: compute_tessellator.h:26
impeller::ComputeTessellator::SetMiterLimit
ComputeTessellator & SetMiterLimit(Scalar value)
Definition: compute_tessellator.cc:50
impeller::CommandBuffer::CompletionCallback
std::function< void(Status)> CompletionCallback
Definition: command_buffer.h:55
impeller::CreateDeviceBuffer
static std::shared_ptr< DeviceBuffer > CreateDeviceBuffer(const std::shared_ptr< Context > &context, const std::string &label, StorageMode storage_mode=StorageMode::kDevicePrivate)
Definition: compute_tessellator.cc:20
impeller::ComputeTessellator
A utility that generates triangles of the specified fill type given a path.
Definition: compute_tessellator.h:20
impeller::ComputeTessellator::SetStrokeJoin
ComputeTessellator & SetStrokeJoin(Join value)
Definition: compute_tessellator.cc:42
impeller::ComputeTessellator::Style::kStroke
@ kStroke
impeller::ComputeTessellator::Status::kOk
@ kOk
impeller::ComputeTessellator::SetCubicAccuracy
ComputeTessellator & SetCubicAccuracy(Scalar value)
Definition: compute_tessellator.cc:54
impeller::StorageMode
StorageMode
Specified where the allocation resides and how it is used.
Definition: formats.h:27
impeller::Path::EnumerateComponents
void EnumerateComponents(const Applier< LinearPathComponent > &linear_applier, const Applier< QuadraticPathComponent > &quad_applier, const Applier< CubicPathComponent > &cubic_applier, const Applier< ContourComponent > &contour_applier) const
Definition: path.cc:129
impeller::ComputeTessellator::Style
Style
Definition: compute_tessellator.h:38
impeller::Path
Paths are lightweight objects that describe a collection of linear, quadratic, or cubic segments....
Definition: path.h:55
impeller::ComputeTessellator::SetStrokeWidth
ComputeTessellator & SetStrokeWidth(Scalar value)
Definition: compute_tessellator.cc:37
impeller::StorageMode::kDevicePrivate
@ kDevicePrivate
impeller::DeviceBufferDescriptor::storage_mode
StorageMode storage_mode
Definition: device_buffer_descriptor.h:15
impeller::ComputeTessellator::Tessellate
Status Tessellate(const Path &path, const std::shared_ptr< Context > &context, BufferView vertex_buffer, BufferView vertex_buffer_count, const CommandBuffer::CompletionCallback &callback=nullptr) const
Generates triangles from the path. If the data needs to be synchronized back to the CPU,...
Definition: compute_tessellator.cc:63
impeller::ComputeTessellator::kMaxQuadCount
static constexpr size_t kMaxQuadCount
Definition: compute_tessellator.h:27
pipeline_library.h
impeller::ComputeTessellator::SetStyle
ComputeTessellator & SetStyle(Style value)
Definition: compute_tessellator.cc:32
impeller::CubicPathComponent
Definition: path_component.h:94
impeller::ISize
TSize< int64_t > ISize
Definition: size.h:138
command_buffer.h
impeller::ComputeCommand
An object used to specify compute work to the GPU along with references to resources the GPU will use...
Definition: compute_command.h:36
impeller::BufferView
Definition: buffer_view.h:13
impeller::Join
Join
Definition: path.h:24
impeller::Path::GetComponentCount
size_t GetComponentCount(std::optional< ComponentType > type={}) const
Definition: path.cc:34
impeller::ComputeTessellator::kMaxLineCount
static constexpr size_t kMaxLineCount
Definition: compute_tessellator.h:28
impeller::ContourComponent
Definition: path_component.h:146
impeller::ComputeTessellator::~ComputeTessellator
~ComputeTessellator()
impeller::ComputeTessellator::ComputeTessellator
ComputeTessellator()
impeller
Definition: aiks_context.cc:10
impeller::QuadraticPathComponent
Definition: path_component.h:52
impeller::Cap
Cap
Definition: path.h:18
impeller::ComputePipelineBuilder
An optional (but highly recommended) utility for creating pipelines from reflected shader information...
Definition: compute_pipeline_builder.h:25