Flutter Engine
The Flutter Engine
render_target.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
6
7#include <sstream>
8
16
17namespace impeller {
18
20
22
24 // Validate that there is a color attachment at zero index.
25 if (!HasColorAttachment(0u)) {
27 << "Render target does not have color attachment at index 0.";
28 return false;
29 }
30
31 // Validate that all attachments are of the same size.
32 {
33 std::optional<ISize> size;
34 bool sizes_are_same = true;
35 auto iterator = [&](const Attachment& attachment) -> bool {
36 if (!size.has_value()) {
37 size = attachment.texture->GetSize();
38 }
39 if (size != attachment.texture->GetSize()) {
40 sizes_are_same = false;
41 return false;
42 }
43 return true;
44 };
45 IterateAllAttachments(iterator);
46 if (!sizes_are_same) {
48 << "Sizes of all render target attachments are not the same.";
49 return false;
50 }
51 }
52
53 // Validate that all attachments are of the same type and sample counts.
54 {
55 std::optional<TextureType> texture_type;
56 std::optional<SampleCount> sample_count;
57 bool passes_type_validation = true;
58 auto iterator = [&](const Attachment& attachment) -> bool {
59 if (!texture_type.has_value() || !sample_count.has_value()) {
60 texture_type = attachment.texture->GetTextureDescriptor().type;
61 sample_count = attachment.texture->GetTextureDescriptor().sample_count;
62 }
63
64 if (texture_type != attachment.texture->GetTextureDescriptor().type) {
65 passes_type_validation = false;
66 VALIDATION_LOG << "Render target has incompatible texture types: "
67 << TextureTypeToString(texture_type.value()) << " != "
69 attachment.texture->GetTextureDescriptor().type)
70 << " on target " << ToString();
71 return false;
72 }
73
74 if (sample_count !=
75 attachment.texture->GetTextureDescriptor().sample_count) {
76 passes_type_validation = false;
77 VALIDATION_LOG << "Render target (" << ToString()
78 << ") has incompatible sample counts.";
79
80 return false;
81 }
82
83 return true;
84 };
85 IterateAllAttachments(iterator);
86 if (!passes_type_validation) {
87 return false;
88 }
89 }
90
91 return true;
92}
93
95 const std::function<bool(const Attachment& attachment)>& iterator) const {
96 for (const auto& color : colors_) {
97 if (!iterator(color.second)) {
98 return;
99 }
100 }
101
102 if (depth_.has_value()) {
103 if (!iterator(depth_.value())) {
104 return;
105 }
106 }
107
108 if (stencil_.has_value()) {
109 if (!iterator(stencil_.value())) {
110 return;
111 }
112 }
113}
114
116 if (auto found = colors_.find(0u); found != colors_.end()) {
117 return found->second.texture->GetTextureDescriptor().sample_count;
118 }
120}
121
122bool RenderTarget::HasColorAttachment(size_t index) const {
123 if (auto found = colors_.find(index); found != colors_.end()) {
124 return true;
125 }
126 return false;
127}
128
129std::optional<ISize> RenderTarget::GetColorAttachmentSize(size_t index) const {
130 auto found = colors_.find(index);
131
132 if (found == colors_.end()) {
133 return std::nullopt;
134 }
135
136 return found->second.texture->GetSize();
137}
138
140 auto size = GetColorAttachmentSize(0u);
141 return size.has_value() ? size.value() : ISize{};
142}
143
144std::shared_ptr<Texture> RenderTarget::GetRenderTargetTexture() const {
145 auto found = colors_.find(0u);
146 if (found == colors_.end()) {
147 return nullptr;
148 }
149 return found->second.resolve_texture ? found->second.resolve_texture
150 : found->second.texture;
151}
152
154 if (auto texture = GetRenderTargetTexture(); texture != nullptr) {
155 return texture->GetTextureDescriptor().format;
156 }
157
159}
160
162 size_t max = 0;
163 for (const auto& color : colors_) {
164 max = std::max(color.first, max);
165 }
166 return max;
167}
168
170 const ColorAttachment& attachment,
171 size_t index) {
172 if (attachment.IsValid()) {
173 colors_[index] = attachment;
174 }
175 return *this;
176}
177
179 std::optional<DepthAttachment> attachment) {
180 if (!attachment.has_value()) {
181 depth_ = std::nullopt;
182 } else if (attachment->IsValid()) {
183 depth_ = std::move(attachment);
184 }
185 return *this;
186}
187
189 std::optional<StencilAttachment> attachment) {
190 if (!attachment.has_value()) {
191 stencil_ = std::nullopt;
192 } else if (attachment->IsValid()) {
193 stencil_ = std::move(attachment);
194 }
195 return *this;
196}
197
198const std::map<size_t, ColorAttachment>& RenderTarget::GetColorAttachments()
199 const {
200 return colors_;
201}
202
203const std::optional<DepthAttachment>& RenderTarget::GetDepthAttachment() const {
204 return depth_;
205}
206
207const std::optional<StencilAttachment>& RenderTarget::GetStencilAttachment()
208 const {
209 return stencil_;
210}
211
213 size_t count = 0u;
214 for (const auto& [_, color] : colors_) {
215 if (color.texture) {
216 count++;
217 }
218 if (color.resolve_texture) {
219 count++;
220 }
221 }
222 if (depth_.has_value()) {
223 count++;
224 }
225 if (stencil_.has_value()) {
226 count++;
227 }
228 return count;
229}
230
231std::string RenderTarget::ToString() const {
232 std::stringstream stream;
233
234 for (const auto& [index, color] : colors_) {
235 stream << SPrintF("Color[%zu]=(%s)", index,
237 }
238 if (depth_) {
239 stream << ",";
240 stream << SPrintF("Depth=(%s)",
241 DepthAttachmentToString(depth_.value()).c_str());
242 }
243 if (stencil_) {
244 stream << ",";
245 stream << SPrintF("Stencil=(%s)",
246 StencilAttachmentToString(stencil_.value()).c_str());
247 }
248 return stream.str();
249}
250
252 std::shared_ptr<Allocator> allocator)
253 : allocator_(std::move(allocator)) {}
254
256
258
260 const Context& context,
261 ISize size,
262 int mip_count,
263 const std::string& label,
264 RenderTarget::AttachmentConfig color_attachment_config,
265 std::optional<RenderTarget::AttachmentConfig> stencil_attachment_config,
266 const std::shared_ptr<Texture>& existing_color_texture,
267 const std::shared_ptr<Texture>& existing_depth_stencil_texture) {
268 if (size.IsEmpty()) {
269 return {};
270 }
271
273
274 std::shared_ptr<Texture> color0_tex;
275 if (existing_color_texture) {
276 color0_tex = existing_color_texture;
277 } else {
278 PixelFormat pixel_format =
279 context.GetCapabilities()->GetDefaultColorFormat();
280 TextureDescriptor color0_tex_desc;
281 color0_tex_desc.storage_mode = color_attachment_config.storage_mode;
282 color0_tex_desc.format = pixel_format;
283 color0_tex_desc.size = size;
284 color0_tex_desc.mip_count = mip_count;
285 color0_tex_desc.usage =
287 color0_tex = allocator_->CreateTexture(color0_tex_desc);
288 if (!color0_tex) {
289 return {};
290 }
291 }
292 color0_tex->SetLabel(SPrintF("%s Color Texture", label.c_str()));
293
294 ColorAttachment color0;
295 color0.clear_color = color_attachment_config.clear_color;
296 color0.load_action = color_attachment_config.load_action;
297 color0.store_action = color_attachment_config.store_action;
298 color0.texture = color0_tex;
299 target.SetColorAttachment(color0, 0u);
300
301 if (stencil_attachment_config.has_value()) {
302 target.SetupDepthStencilAttachments(
303 context, *allocator_, size, false, label,
304 stencil_attachment_config.value(), existing_depth_stencil_texture);
305 } else {
306 target.SetStencilAttachment(std::nullopt);
307 target.SetDepthAttachment(std::nullopt);
308 }
309
310 return target;
311}
312
314 const Context& context,
315 ISize size,
316 int mip_count,
317 const std::string& label,
318 RenderTarget::AttachmentConfigMSAA color_attachment_config,
319 std::optional<RenderTarget::AttachmentConfig> stencil_attachment_config,
320 const std::shared_ptr<Texture>& existing_color_msaa_texture,
321 const std::shared_ptr<Texture>& existing_color_resolve_texture,
322 const std::shared_ptr<Texture>& existing_depth_stencil_texture) {
323 if (size.IsEmpty()) {
324 return {};
325 }
326
328 PixelFormat pixel_format = context.GetCapabilities()->GetDefaultColorFormat();
329
330 // Create MSAA color texture.
331 std::shared_ptr<Texture> color0_msaa_tex;
332 if (existing_color_msaa_texture) {
333 color0_msaa_tex = existing_color_msaa_texture;
334 } else {
335 TextureDescriptor color0_tex_desc;
336 color0_tex_desc.storage_mode = color_attachment_config.storage_mode;
338 color0_tex_desc.sample_count = SampleCount::kCount4;
339 color0_tex_desc.format = pixel_format;
340 color0_tex_desc.size = size;
341 color0_tex_desc.usage = TextureUsage::kRenderTarget;
342 if (context.GetCapabilities()->SupportsImplicitResolvingMSAA()) {
343 // See below ("SupportsImplicitResolvingMSAA") for more details.
345 }
346 color0_msaa_tex = allocator_->CreateTexture(color0_tex_desc);
347 if (!color0_msaa_tex) {
348 VALIDATION_LOG << "Could not create multisample color texture.";
349 return {};
350 }
351 }
352 color0_msaa_tex->SetLabel(
353 SPrintF("%s Color Texture (Multisample)", label.c_str()));
354
355 // Create color resolve texture.
356 std::shared_ptr<Texture> color0_resolve_tex;
357 if (existing_color_resolve_texture) {
358 color0_resolve_tex = existing_color_resolve_texture;
359 } else {
360 TextureDescriptor color0_resolve_tex_desc;
361 color0_resolve_tex_desc.storage_mode =
362 color_attachment_config.resolve_storage_mode;
363 color0_resolve_tex_desc.format = pixel_format;
364 color0_resolve_tex_desc.size = size;
365 color0_resolve_tex_desc.compression_type = CompressionType::kLossy;
366 color0_resolve_tex_desc.usage =
368 color0_resolve_tex_desc.mip_count = mip_count;
369 color0_resolve_tex = allocator_->CreateTexture(color0_resolve_tex_desc);
370 if (!color0_resolve_tex) {
371 VALIDATION_LOG << "Could not create color texture.";
372 return {};
373 }
374 }
375 color0_resolve_tex->SetLabel(SPrintF("%s Color Texture", label.c_str()));
376
377 // Color attachment.
378
379 ColorAttachment color0;
380 color0.clear_color = color_attachment_config.clear_color;
381 color0.load_action = color_attachment_config.load_action;
382 color0.store_action = color_attachment_config.store_action;
383 color0.texture = color0_msaa_tex;
384 color0.resolve_texture = color0_resolve_tex;
385
386 if (context.GetCapabilities()->SupportsImplicitResolvingMSAA()) {
387 // If implicit MSAA is supported, then the resolve texture is not needed
388 // because the multisample texture is automatically resolved. We instead
389 // provide a view of the multisample texture as the resolve texture (because
390 // the HAL does expect a resolve texture).
391 //
392 // In practice, this is used for GLES 2.0 EXT_multisampled_render_to_texture
393 // https://registry.khronos.org/OpenGL/extensions/EXT/EXT_multisampled_render_to_texture.txt
394 color0.resolve_texture = color0_msaa_tex;
395 }
396
397 target.SetColorAttachment(color0, 0u);
398
399 // Create MSAA stencil texture.
400
401 if (stencil_attachment_config.has_value()) {
402 target.SetupDepthStencilAttachments(context, *allocator_, size, true, label,
403 stencil_attachment_config.value(),
404 existing_depth_stencil_texture);
405 } else {
406 target.SetDepthAttachment(std::nullopt);
407 target.SetStencilAttachment(std::nullopt);
408 }
409
410 return target;
411}
412
414 const Context& context,
415 Allocator& allocator,
416 ISize size,
417 bool msaa,
418 const std::string& label,
419 RenderTarget::AttachmentConfig stencil_attachment_config,
420 const std::shared_ptr<Texture>& existing_depth_stencil_texture) {
421 std::shared_ptr<Texture> depth_stencil_texture;
422 if (existing_depth_stencil_texture) {
423 depth_stencil_texture = existing_depth_stencil_texture;
424 } else {
425 TextureDescriptor depth_stencil_texture_desc;
426 depth_stencil_texture_desc.storage_mode =
427 stencil_attachment_config.storage_mode;
428 if (msaa) {
429 depth_stencil_texture_desc.type = TextureType::kTexture2DMultisample;
430 depth_stencil_texture_desc.sample_count = SampleCount::kCount4;
431 }
432 depth_stencil_texture_desc.format =
433 context.GetCapabilities()->GetDefaultDepthStencilFormat();
434 depth_stencil_texture_desc.size = size;
435 depth_stencil_texture_desc.usage = TextureUsage::kRenderTarget;
436 depth_stencil_texture = allocator.CreateTexture(depth_stencil_texture_desc);
437 if (!depth_stencil_texture) {
438 return; // Error messages are handled by `Allocator::CreateTexture`.
439 }
440 }
441
442 DepthAttachment depth0;
443 depth0.load_action = stencil_attachment_config.load_action;
444 depth0.store_action = stencil_attachment_config.store_action;
445 depth0.clear_depth = 0u;
446 depth0.texture = depth_stencil_texture;
447
448 StencilAttachment stencil0;
449 stencil0.load_action = stencil_attachment_config.load_action;
450 stencil0.store_action = stencil_attachment_config.store_action;
451 stencil0.clear_stencil = 0u;
452 stencil0.texture = std::move(depth_stencil_texture);
453
454 stencil0.texture->SetLabel(
455 SPrintF("%s Depth+Stencil Texture", label.c_str()));
456 SetDepthAttachment(std::move(depth0));
457 SetStencilAttachment(std::move(stencil0));
458}
459
460} // namespace impeller
int count
Definition: FontMgrTest.cpp:50
An object that allocates device memory.
Definition: allocator.h:22
std::shared_ptr< Texture > CreateTexture(const TextureDescriptor &desc)
Definition: allocator.cc:49
To do anything rendering related with Impeller, you need a context.
Definition: context.h:45
virtual const std::shared_ptr< const Capabilities > & GetCapabilities() const =0
Get the capabilities of Impeller context. All optionally supported feature of the platform,...
RenderTargetAllocator(std::shared_ptr< Allocator > allocator)
virtual RenderTarget CreateOffscreen(const Context &context, ISize size, int mip_count, const std::string &label="Offscreen", RenderTarget::AttachmentConfig color_attachment_config=RenderTarget::kDefaultColorAttachmentConfig, std::optional< RenderTarget::AttachmentConfig > stencil_attachment_config=RenderTarget::kDefaultStencilAttachmentConfig, const std::shared_ptr< Texture > &existing_color_texture=nullptr, const std::shared_ptr< Texture > &existing_depth_stencil_texture=nullptr)
virtual void Start()
Mark the beginning of a frame workload.
virtual RenderTarget CreateOffscreenMSAA(const Context &context, ISize size, int mip_count, const std::string &label="Offscreen MSAA", RenderTarget::AttachmentConfigMSAA color_attachment_config=RenderTarget::kDefaultColorAttachmentConfigMSAA, std::optional< RenderTarget::AttachmentConfig > stencil_attachment_config=RenderTarget::kDefaultStencilAttachmentConfig, const std::shared_ptr< Texture > &existing_color_msaa_texture=nullptr, const std::shared_ptr< Texture > &existing_color_resolve_texture=nullptr, const std::shared_ptr< Texture > &existing_depth_stencil_texture=nullptr)
virtual void End()
Mark the end of a frame workload.
std::shared_ptr< Texture > GetRenderTargetTexture() const
const std::map< size_t, ColorAttachment > & GetColorAttachments() const
SampleCount GetSampleCount() const
void IterateAllAttachments(const std::function< bool(const Attachment &attachment)> &iterator) const
RenderTarget & SetColorAttachment(const ColorAttachment &attachment, size_t index)
void SetupDepthStencilAttachments(const Context &context, Allocator &allocator, ISize size, bool msaa, const std::string &label="Offscreen", RenderTarget::AttachmentConfig stencil_attachment_config=RenderTarget::kDefaultStencilAttachmentConfig, const std::shared_ptr< Texture > &depth_stencil_texture=nullptr)
bool HasColorAttachment(size_t index) const
size_t GetMaxColorAttacmentBindIndex() const
std::string ToString() const
RenderTarget & SetDepthAttachment(std::optional< DepthAttachment > attachment)
PixelFormat GetRenderTargetPixelFormat() const
size_t GetTotalAttachmentCount() const
ISize GetRenderTargetSize() const
RenderTarget & SetStencilAttachment(std::optional< StencilAttachment > attachment)
std::optional< ISize > GetColorAttachmentSize(size_t index) const
const std::optional< DepthAttachment > & GetDepthAttachment() const
const std::optional< StencilAttachment > & GetStencilAttachment() const
DlColor color
uint32_t * target
Dart_NativeFunction function
Definition: fuchsia.cc:51
static float max(float r, float g, float b)
Definition: hsl.cpp:49
FlTexture * texture
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
std::string DepthAttachmentToString(const DepthAttachment &depth)
Definition: formats.cc:130
std::string ColorAttachmentToString(const ColorAttachment &color)
Definition: formats.cc:123
std::string StencilAttachmentToString(const StencilAttachment &stencil)
Definition: formats.cc:137
std::string SPrintF(const char *format,...)
Definition: strings.cc:12
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition: formats.h:99
constexpr const char * TextureTypeToString(TextureType type)
Definition: formats.h:269
SampleCount
Definition: formats.h:295
Definition: ref_ptr.h:256
std::shared_ptr< Texture > resolve_texture
Definition: formats.h:652
bool IsValid() const
Definition: formats.cc:26
LoadAction load_action
Definition: formats.h:653
std::shared_ptr< Texture > texture
Definition: formats.h:651
StoreAction store_action
Definition: formats.h:654
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
#define VALIDATION_LOG
Definition: validation.h:73