| Flutter Impeller |

render_pass.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/render_pass.h"
6
7 #include <utility>
8 #include "fml/status.h"
9 #include "impeller/base/validation.h"
10 #include "impeller/core/vertex_buffer.h"
11
12 namespace impeller {
13
14 RenderPass::RenderPass(std::shared_ptr<const Context> context,
15 const RenderTarget& target)
16 : context_(std::move(context)),
17 sample_count_(target.GetSampleCount()),
18 pixel_format_(target.GetRenderTargetPixelFormat()),
19 has_depth_attachment_(target.GetDepthAttachment().has_value()),
20 has_stencil_attachment_(target.GetStencilAttachment().has_value()),
21 render_target_size_(target.GetRenderTargetSize()),
22 render_target_(target),
23 orthographic_(Matrix::MakeOrthographic(render_target_size_)) {}
24
25 RenderPass::~RenderPass() {}
26
27 SampleCount RenderPass::GetSampleCount() const {
28 return sample_count_;
29 }
30
31 PixelFormat RenderPass::GetRenderTargetPixelFormat() const {
32 return pixel_format_;
33 }
34
35 bool RenderPass::HasDepthAttachment() const {
36 return has_depth_attachment_;
37 }
38
39 bool RenderPass::HasStencilAttachment() const {
40 return has_stencil_attachment_;
41 }
42
43 const RenderTarget& RenderPass::GetRenderTarget() const {
44 return render_target_;
45 }
46
47 ISize RenderPass::GetRenderTargetSize() const {
48 return render_target_size_;
49 }
50
51 const Matrix& RenderPass::GetOrthographicTransform() const {
52 return orthographic_;
53 }
54
55 void RenderPass::SetLabel(std::string_view label) {
56 if (label.empty()) {
57 return;
58 }
59 OnSetLabel(label);
60 }
61
62 bool RenderPass::AddCommand(Command&& command) {
63 if (!command.IsValid()) {
64 VALIDATION_LOG << "Attempted to add an invalid command to the render pass.";
65 return false;
66 }
67
68 if (command.element_count == 0u || command.instance_count == 0u) {
69 // Essentially a no-op. Don't record the command but this is not necessary
70 // an error either.
71 return true;
72 }
73
74 commands_.emplace_back(std::move(command));
75 return true;
76 }
77
78 bool RenderPass::EncodeCommands() const {
79 return OnEncodeCommands(*context_);
80 }
81
82 const std::shared_ptr<const Context>& RenderPass::GetContext() const {
83 return context_;
84 }
85
86 void RenderPass::SetPipeline(PipelineRef pipeline) {
87 // On debug this makes a difference, but not on release builds.
88 // NOLINTNEXTLINE(performance-move-const-arg)
89 pending_.pipeline = std::move(pipeline);
90 }
91
92 void RenderPass::SetPipeline(
93 const std::shared_ptr<Pipeline<PipelineDescriptor>>& pipeline) {
94 SetPipeline(PipelineRef(pipeline));
95 }
96
97 void RenderPass::SetCommandLabel(std::string_view label) {
98 #ifdef IMPELLER_DEBUG
99 pending_.label = std::string(label);
100 #endif // IMPELLER_DEBUG
101 }
102
103 void RenderPass::SetStencilReference(uint32_t value) {
104 pending_.stencil_reference = value;
105 }
106
107 void RenderPass::SetBaseVertex(uint64_t value) {
108 pending_.base_vertex = value;
109 }
110
111 void RenderPass::SetViewport(Viewport viewport) {
112 pending_.viewport = viewport;
113 }
114
115 void RenderPass::SetScissor(IRect scissor) {
116 pending_.scissor = scissor;
117 }
118
119 void RenderPass::SetElementCount(size_t count) {
120 pending_.element_count = count;
121 }
122
123 void RenderPass::SetInstanceCount(size_t count) {
124 pending_.instance_count = count;
125 }
126
127 bool RenderPass::SetVertexBuffer(VertexBuffer buffer) {
128 if (!SetVertexBuffer(&buffer.vertex_buffer, 1u)) {
129 return false;
130 }
131 if (!SetIndexBuffer(buffer.index_buffer, buffer.index_type)) {
132 return false;
133 }
134 SetElementCount(buffer.vertex_count);
135
136 return true;
137 }
138
139 bool RenderPass::SetVertexBuffer(BufferView vertex_buffer) {
140 return SetVertexBuffer(&vertex_buffer, 1);
141 }
142
143 bool RenderPass::SetVertexBuffer(std::vector<BufferView> vertex_buffers) {
144 return SetVertexBuffer(vertex_buffers.data(), vertex_buffers.size());
145 }
146
147 bool RenderPass::SetVertexBuffer(BufferView vertex_buffers[],
148 size_t vertex_buffer_count) {
149 if (!ValidateVertexBuffers(vertex_buffers, vertex_buffer_count)) {
150 return false;
151 }
152
153 if (!vertex_buffers_start_.has_value()) {
154 vertex_buffers_start_ = vertex_buffers_.size();
155 }
156
157 pending_.vertex_buffers.length += vertex_buffer_count;
158 for (size_t i = 0; i < vertex_buffer_count; i++) {
159 vertex_buffers_.push_back(vertex_buffers[i]);
160 }
161 return true;
162 }
163
164 bool RenderPass::SetIndexBuffer(BufferView index_buffer, IndexType index_type) {
165 if (!ValidateIndexBuffer(index_buffer, index_type)) {
166 return false;
167 }
168
169 pending_.index_buffer = std::move(index_buffer);
170 pending_.index_type = index_type;
171 return true;
172 }
173
174 bool RenderPass::ValidateVertexBuffers(const BufferView vertex_buffers[],
175 size_t vertex_buffer_count) {
176 if (vertex_buffer_count > kMaxVertexBuffers) {
177 VALIDATION_LOG << "Attempted to bind " << vertex_buffer_count
178 << " vertex buffers, but the maximum is "
179 << kMaxVertexBuffers << ".";
180 return false;
181 }
182
183 for (size_t i = 0; i < vertex_buffer_count; i++) {
184 if (!vertex_buffers[i]) {
185 VALIDATION_LOG << "Attempted to bind an invalid vertex buffer.";
186 return false;
187 }
188 }
189
190 return true;
191 }
192
193 bool RenderPass::ValidateIndexBuffer(const BufferView& index_buffer,
194 IndexType index_type) {
195 if (index_type == IndexType::kUnknown) {
196 VALIDATION_LOG << "Cannot bind an index buffer with an unknown index type.";
197 return false;
198 }
199
200 if (index_type != IndexType::kNone && !index_buffer) {
201 VALIDATION_LOG << "Attempted to bind an invalid index buffer.";
202 return false;
203 }
204
205 return true;
206 }
207
208 fml::Status RenderPass::Draw() {
209 pending_.bound_buffers.offset = bound_buffers_start_.value_or(0u);
210 pending_.bound_textures.offset = bound_textures_start_.value_or(0u);
211 pending_.vertex_buffers.offset = vertex_buffers_start_.value_or(0u);
212 auto result = AddCommand(std::move(pending_));
213 pending_ = Command{};
214 bound_textures_start_ = std::nullopt;
215 bound_buffers_start_ = std::nullopt;
216 vertex_buffers_start_ = std::nullopt;
217 if (result) {
218 return fml::Status();
219 }
220 return fml::Status(fml::StatusCode::kInvalidArgument,
221 "Failed to encode command");
222 }
223
224 // |ResourceBinder|
225 bool RenderPass::BindResource(ShaderStage stage,
226 DescriptorType type,
227 const ShaderUniformSlot& slot,
228 const ShaderMetadata* metadata,
229 BufferView view) {
230 FML_DCHECK(slot.ext_res_0 != VertexDescriptor::kReservedVertexBufferIndex);
231 if (!view) {
232 return false;
233 }
234 BufferResource resouce = BufferResource(metadata, std::move(view));
235 return BindBuffer(stage, slot, std::move(resouce));
236 }
237
238 // |ResourceBinder|
239 bool RenderPass::BindResource(ShaderStage stage,
240 DescriptorType type,
241 const SampledImageSlot& slot,
242 const ShaderMetadata* metadata,
243 std::shared_ptr<const Texture> texture,
244 raw_ptr<const Sampler> sampler) {
245 if (!sampler) {
246 return false;
247 }
248 if (!texture || !texture->IsValid()) {
249 return false;
250 }
251 TextureResource resource = TextureResource(metadata, std::move(texture));
252 return BindTexture(stage, slot, std::move(resource), sampler);
253 }
254
255 bool RenderPass::BindDynamicResource(ShaderStage stage,
256 DescriptorType type,
257 const ShaderUniformSlot& slot,
258 std::unique_ptr<ShaderMetadata> metadata,
259 BufferView view) {
260 FML_DCHECK(slot.ext_res_0 != VertexDescriptor::kReservedVertexBufferIndex);
261 if (!view) {
262 return false;
263 }
264 BufferResource resouce =
265 BufferResource::MakeDynamic(std::move(metadata), std::move(view));
266
267 return BindBuffer(stage, slot, std::move(resouce));
268 }
269
270 bool RenderPass::BindDynamicResource(
271 ShaderStage stage,
272 DescriptorType type,
273 const SampledImageSlot& slot,
274 std::unique_ptr<ShaderMetadata> metadata,
275 std::shared_ptr<const Texture> texture,
276 raw_ptr<const Sampler>
277 sampler // NOLINT(performance-unnecessary-value-param)
278 ) {
279 if (!sampler) {
280 return false;
281 }
282 if (!texture || !texture->IsValid()) {
283 return false;
284 }
285 TextureResource resource =
286 TextureResource::MakeDynamic(std::move(metadata), std::move(texture));
287 return BindTexture(stage, slot, std::move(resource), sampler);
288 }
289
290 bool RenderPass::BindBuffer(ShaderStage stage,
291 const ShaderUniformSlot& slot,
292 BufferResource resource) {
293 if (!bound_buffers_start_.has_value()) {
294 bound_buffers_start_ = bound_buffers_.size();
295 }
296
297 pending_.bound_buffers.length++;
298 bound_buffers_.push_back(std::move(resource));
299 return true;
300 }
301
302 bool RenderPass::BindTexture(ShaderStage stage,
303 const SampledImageSlot& slot,
304 TextureResource resource,
305 raw_ptr<const Sampler> sampler) {
306 TextureAndSampler data = TextureAndSampler{
307 .stage = stage,
308 .texture = std::move(resource),
309 // NOLINTNEXTLINE(performance-move-const-arg)
310 .sampler = sampler,
311 };
312
313 if (!bound_textures_start_.has_value()) {
314 bound_textures_start_ = bound_textures_.size();
315 }
316
317 pending_.bound_textures.length++;
318 bound_textures_.push_back(std::move(data));
319 return true;
320 }
321
322 } // namespace impeller
type
GLenum type
Definition: blit_command_gles.cc:151
impeller::Pipeline< PipelineDescriptor >
impeller::RenderPass::bound_textures_
std::vector< TextureAndSampler > bound_textures_
Definition: render_pass.h:251
impeller::RenderPass::BindDynamicResource
virtual bool BindDynamicResource(ShaderStage stage, DescriptorType type, const SampledImageSlot &slot, std::unique_ptr< ShaderMetadata > metadata, std::shared_ptr< const Texture > texture, raw_ptr< const Sampler >)
Bind with dynamically generated shader metadata.
Definition: render_pass.cc:270
impeller::RenderPass::has_depth_attachment_
const bool has_depth_attachment_
Definition: render_pass.h:244
impeller::RenderPass::ValidateIndexBuffer
static bool ValidateIndexBuffer(const BufferView &index_buffer, IndexType index_type)
Definition: render_pass.cc:193
impeller::RenderPass::SetVertexBuffer
virtual bool SetVertexBuffer(VertexBuffer buffer)
Specify the vertex and index buffer to use for this command.
Definition: render_pass.cc:127
impeller::RenderPass::BindResource
virtual bool BindResource(ShaderStage stage, DescriptorType type, const ShaderUniformSlot &slot, const ShaderMetadata *metadata, BufferView view) override
Definition: render_pass.cc:225
impeller::RenderPass::has_stencil_attachment_
const bool has_stencil_attachment_
Definition: render_pass.h:245
impeller::RenderPass::SetStencilReference
virtual void SetStencilReference(uint32_t value)
Definition: render_pass.cc:103
impeller::RenderPass::GetRenderTarget
const RenderTarget & GetRenderTarget() const
Definition: render_pass.cc:43
impeller::RenderPass::GetSampleCount
SampleCount GetSampleCount() const
The sample count of the attached render target.
Definition: render_pass.cc:27
impeller::RenderPass::SetIndexBuffer
virtual bool SetIndexBuffer(BufferView index_buffer, IndexType index_type)
Specify an index buffer to use for this command. To unset the index buffer, pass IndexType::kNone to ...
Definition: render_pass.cc:164
impeller::RenderPass::AddCommand
bool AddCommand(Command &&command)
Record a command for subsequent encoding to the underlying command buffer. No work is encoded into th...
Definition: render_pass.cc:62
impeller::RenderPass::sample_count_
const SampleCount sample_count_
Definition: render_pass.h:242
impeller::RenderPass::OnEncodeCommands
virtual bool OnEncodeCommands(const Context &context) const =0
impeller::RenderPass::SetScissor
virtual void SetScissor(IRect scissor)
Definition: render_pass.cc:115
impeller::RenderPass::GetRenderTargetPixelFormat
PixelFormat GetRenderTargetPixelFormat() const
The pixel format of the attached render target.
Definition: render_pass.cc:31
impeller::RenderPass::GetOrthographicTransform
const Matrix & GetOrthographicTransform() const
Definition: render_pass.cc:51
impeller::RenderPass::RenderPass
RenderPass(std::shared_ptr< const Context > context, const RenderTarget &target)
Definition: render_pass.cc:14
impeller::RenderPass::commands_
std::vector< Command > commands_
Definition: render_pass.h:248
impeller::RenderPass::context_
const std::shared_ptr< const Context > context_
Definition: render_pass.h:236
impeller::RenderPass::~RenderPass
virtual ~RenderPass()
Definition: render_pass.cc:25
impeller::RenderPass::bound_buffers_
std::vector< BufferResource > bound_buffers_
Definition: render_pass.h:250
impeller::RenderPass::ValidateVertexBuffers
static bool ValidateVertexBuffers(const BufferView vertex_buffers[], size_t vertex_buffer_count)
Definition: render_pass.cc:174
impeller::RenderPass::HasStencilAttachment
bool HasStencilAttachment() const
Whether the render target has an stencil attachment.
Definition: render_pass.cc:39
impeller::RenderPass::OnSetLabel
virtual void OnSetLabel(std::string_view label)=0
impeller::RenderPass::orthographic_
const Matrix orthographic_
Definition: render_pass.h:252
impeller::RenderPass::SetLabel
void SetLabel(std::string_view label)
Definition: render_pass.cc:55
impeller::RenderPass::vertex_buffers_
std::vector< BufferView > vertex_buffers_
Definition: render_pass.h:249
impeller::RenderPass::SetPipeline
virtual void SetPipeline(PipelineRef pipeline)
The pipeline to use for this command.
Definition: render_pass.cc:86
impeller::RenderPass::render_target_size_
const ISize render_target_size_
Definition: render_pass.h:246
impeller::RenderPass::GetRenderTargetSize
ISize GetRenderTargetSize() const
Definition: render_pass.cc:47
impeller::RenderPass::SetInstanceCount
virtual void SetInstanceCount(size_t count)
Definition: render_pass.cc:123
impeller::RenderPass::Draw
virtual fml::Status Draw()
Record the currently pending command.
Definition: render_pass.cc:208
impeller::RenderPass::HasDepthAttachment
bool HasDepthAttachment() const
Whether the render target has a depth attachment.
Definition: render_pass.cc:35
impeller::RenderPass::SetElementCount
virtual void SetElementCount(size_t count)
Definition: render_pass.cc:119
impeller::RenderPass::SetCommandLabel
virtual void SetCommandLabel(std::string_view label)
The debugging label to use for the command.
Definition: render_pass.cc:97
impeller::RenderPass::EncodeCommands
bool EncodeCommands() const
Encode the recorded commands to the underlying command buffer.
Definition: render_pass.cc:78
impeller::RenderPass::GetContext
const std::shared_ptr< const Context > & GetContext() const
Definition: render_pass.cc:82
impeller::RenderPass::SetBaseVertex
virtual void SetBaseVertex(uint64_t value)
Definition: render_pass.cc:107
impeller::RenderPass::SetViewport
virtual void SetViewport(Viewport viewport)
Definition: render_pass.cc:111
impeller::RenderPass::render_target_
const RenderTarget render_target_
Definition: render_pass.h:247
impeller::RenderPass::pixel_format_
const PixelFormat pixel_format_
Definition: render_pass.h:243
impeller::RenderTarget
Definition: render_target.h:38
impeller::Resource
Definition: command.h:24
impeller::Resource::MakeDynamic
static Resource MakeDynamic(std::unique_ptr< ShaderMetadata > metadata, ResourceType p_resource)
Definition: command.h:38
impeller::VertexDescriptor::kReservedVertexBufferIndex
static constexpr size_t kReservedVertexBufferIndex
Definition: vertex_descriptor.h:25
impeller::raw_ptr< Pipeline< PipelineDescriptor > >
value
int32_t value
Definition: dl_golden_unittests.cc:459
impeller
Definition: allocation.cc:12
impeller::IndexType
IndexType
Definition: formats.h:343
impeller::IndexType::kUnknown
@ kUnknown
impeller::IndexType::kNone
@ kNone
Does not use the index buffer.
impeller::TextureResource
Resource< std::shared_ptr< const Texture > > TextureResource
Definition: command.h:55
impeller::PipelineRef
raw_ptr< Pipeline< PipelineDescriptor > > PipelineRef
A raw ptr to a pipeline object.
Definition: pipeline.h:88
impeller::BufferResource
Resource< BufferView > BufferResource
Definition: command.h:54
impeller::PixelFormat
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition: formats.h:99
impeller::kMaxVertexBuffers
constexpr size_t kMaxVertexBuffers
Definition: vertex_buffer.h:13
impeller::ShaderStage
ShaderStage
Definition: shader_types.h:22
impeller::DescriptorType
DescriptorType
Definition: shader_types.h:158
impeller::SampleCount
SampleCount
Definition: formats.h:295
std
Definition: comparable.h:95
render_pass.h
impeller::BufferView
Definition: buffer_view.h:19
impeller::Command
An object used to specify work to the GPU along with references to resources the GPU will used when d...
Definition: command.h:79
impeller::Command::bound_textures
Range bound_textures
Definition: command.h:88
impeller::Command::base_vertex
uint64_t base_vertex
Definition: command.h:108
impeller::Command::stencil_reference
uint32_t stencil_reference
Definition: command.h:104
impeller::Command::index_buffer
BufferView index_buffer
The index buffer binding used by the vertex shader stage.
Definition: command.h:139
impeller::Command::viewport
std::optional< Viewport > viewport
Definition: command.h:115
impeller::Command::vertex_buffers
Range vertex_buffers
Definition: command.h:135
impeller::Command::bound_buffers
Range bound_buffers
Definition: command.h:87
impeller::Command::pipeline
PipelineRef pipeline
Definition: command.h:83
impeller::Command::scissor
std::optional< IRect > scissor
Definition: command.h:121
impeller::Command::index_type
IndexType index_type
Definition: command.h:149
impeller::Command::element_count
size_t element_count
Definition: command.h:144
impeller::Command::instance_count
size_t instance_count
Definition: command.h:129
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
impeller::Range::length
size_t length
Definition: range.h:15
impeller::Range::offset
size_t offset
Definition: range.h:14
impeller::SampledImageSlot
Metadata required to bind a combined texture and sampler.
Definition: shader_types.h:98
impeller::ShaderMetadata
Definition: shader_types.h:72
impeller::ShaderUniformSlot
Metadata required to bind a buffer.
Definition: shader_types.h:81
impeller::ShaderUniformSlot::ext_res_0
size_t ext_res_0
ext_res_0 is the Metal binding value.
Definition: shader_types.h:86
impeller::TRect
Definition: rect.h:122
impeller::TSize
Definition: size.h:25
impeller::VertexBuffer
Definition: vertex_buffer.h:15
impeller::VertexBuffer::index_type
IndexType index_type
Definition: vertex_buffer.h:31
impeller::VertexBuffer::vertex_count
size_t vertex_count
Definition: vertex_buffer.h:25
impeller::VertexBuffer::index_buffer
BufferView index_buffer
The index buffer binding used by the vertex shader stage.
Definition: vertex_buffer.h:20
impeller::VertexBuffer::vertex_buffer
BufferView vertex_buffer
Definition: vertex_buffer.h:16
impeller::Viewport
Definition: formats.h:403
data
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:67
validation.h
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:91
vertex_buffer.h