Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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
SkColor4f color
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:46
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
uint32_t * target
static float max(float r, float g, float b)
Definition hsl.cpp:49
FlTexture * texture
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:100
constexpr const char * TextureTypeToString(TextureType type)
Definition formats.h:270
Definition ref_ptr.h:256
std::shared_ptr< Texture > resolve_texture
Definition formats.h:640
bool IsValid() const
Definition formats.cc:26
LoadAction load_action
Definition formats.h:641
std::shared_ptr< Texture > texture
Definition formats.h:639
StoreAction store_action
Definition formats.h:642
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