Flutter Impeller
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 
12 #include "impeller/core/texture.h"
14 
15 namespace impeller {
16 
18  std::shared_ptr<Allocator> allocator)
19  : allocator_(std::move(allocator)) {}
20 
22 
24 
25 std::shared_ptr<Texture> RenderTargetAllocator::CreateTexture(
26  const TextureDescriptor& desc) {
27  return allocator_->CreateTexture(desc);
28 }
29 
30 RenderTarget::RenderTarget() = default;
31 
32 RenderTarget::~RenderTarget() = default;
33 
34 bool RenderTarget::IsValid() const {
35  // Validate that there is a color attachment at zero index.
36  if (!HasColorAttachment(0u)) {
38  << "Render target does not have color attachment at index 0.";
39  return false;
40  }
41 
42  // Validate that all attachments are of the same size.
43  {
44  std::optional<ISize> size;
45  bool sizes_are_same = true;
46  auto iterator = [&](const Attachment& attachment) -> bool {
47  if (!size.has_value()) {
48  size = attachment.texture->GetSize();
49  }
50  if (size != attachment.texture->GetSize()) {
51  sizes_are_same = false;
52  return false;
53  }
54  return true;
55  };
56  IterateAllAttachments(iterator);
57  if (!sizes_are_same) {
59  << "Sizes of all render target attachments are not the same.";
60  return false;
61  }
62  }
63 
64  // Validate that all attachments are of the same type and sample counts.
65  {
66  std::optional<TextureType> texture_type;
67  std::optional<SampleCount> sample_count;
68  bool passes_type_validation = true;
69  auto iterator = [&](const Attachment& attachment) -> bool {
70  if (!texture_type.has_value() || !sample_count.has_value()) {
71  texture_type = attachment.texture->GetTextureDescriptor().type;
72  sample_count = attachment.texture->GetTextureDescriptor().sample_count;
73  }
74 
75  if (texture_type != attachment.texture->GetTextureDescriptor().type) {
76  passes_type_validation = false;
77  VALIDATION_LOG << "Render target has incompatible texture types: "
78  << TextureTypeToString(texture_type.value()) << " != "
80  attachment.texture->GetTextureDescriptor().type)
81  << " on target " << ToString();
82  return false;
83  }
84 
85  if (sample_count !=
86  attachment.texture->GetTextureDescriptor().sample_count) {
87  passes_type_validation = false;
88  VALIDATION_LOG << "Render target (" << ToString()
89  << ") has incompatible sample counts.";
90 
91  return false;
92  }
93 
94  return true;
95  };
96  IterateAllAttachments(iterator);
97  if (!passes_type_validation) {
98  return false;
99  }
100  }
101 
102  return true;
103 }
104 
106  const std::function<bool(const Attachment& attachment)>& iterator) const {
107  for (const auto& color : colors_) {
108  if (!iterator(color.second)) {
109  return;
110  }
111  }
112 
113  if (depth_.has_value()) {
114  if (!iterator(depth_.value())) {
115  return;
116  }
117  }
118 
119  if (stencil_.has_value()) {
120  if (!iterator(stencil_.value())) {
121  return;
122  }
123  }
124 }
125 
127  if (auto found = colors_.find(0u); found != colors_.end()) {
128  return found->second.texture->GetTextureDescriptor().sample_count;
129  }
130  return SampleCount::kCount1;
131 }
132 
133 bool RenderTarget::HasColorAttachment(size_t index) const {
134  if (auto found = colors_.find(index); found != colors_.end()) {
135  return true;
136  }
137  return false;
138 }
139 
140 std::optional<ISize> RenderTarget::GetColorAttachmentSize(size_t index) const {
141  auto found = colors_.find(index);
142 
143  if (found == colors_.end()) {
144  return std::nullopt;
145  }
146 
147  return found->second.texture->GetSize();
148 }
149 
151  auto size = GetColorAttachmentSize(0u);
152  return size.has_value() ? size.value() : ISize{};
153 }
154 
155 std::shared_ptr<Texture> RenderTarget::GetRenderTargetTexture() const {
156  auto found = colors_.find(0u);
157  if (found == colors_.end()) {
158  return nullptr;
159  }
160  return found->second.resolve_texture ? found->second.resolve_texture
161  : found->second.texture;
162 }
163 
165  if (auto texture = GetRenderTargetTexture(); texture != nullptr) {
166  return texture->GetTextureDescriptor().format;
167  }
168 
169  return PixelFormat::kUnknown;
170 }
171 
173  size_t max = 0;
174  for (const auto& color : colors_) {
175  max = std::max(color.first, max);
176  }
177  return max;
178 }
179 
181  const ColorAttachment& attachment,
182  size_t index) {
183  if (attachment.IsValid()) {
184  colors_[index] = attachment;
185  }
186  return *this;
187 }
188 
190  std::optional<DepthAttachment> attachment) {
191  if (!attachment.has_value()) {
192  depth_ = std::nullopt;
193  } else if (attachment->IsValid()) {
194  depth_ = std::move(attachment);
195  }
196  return *this;
197 }
198 
200  std::optional<StencilAttachment> attachment) {
201  if (!attachment.has_value()) {
202  stencil_ = std::nullopt;
203  } else if (attachment->IsValid()) {
204  stencil_ = std::move(attachment);
205  }
206  return *this;
207 }
208 
209 const std::map<size_t, ColorAttachment>& RenderTarget::GetColorAttachments()
210  const {
211  return colors_;
212 }
213 
214 const std::optional<DepthAttachment>& RenderTarget::GetDepthAttachment() const {
215  return depth_;
216 }
217 
218 const std::optional<StencilAttachment>& RenderTarget::GetStencilAttachment()
219  const {
220  return stencil_;
221 }
222 
224  const Context& context,
225  RenderTargetAllocator& allocator,
226  ISize size,
227  const std::string& label,
228  AttachmentConfig color_attachment_config,
229  std::optional<AttachmentConfig> stencil_attachment_config) {
230  if (size.IsEmpty()) {
231  return {};
232  }
233 
234 // Dont force additional PSO variants on Vulkan.
235 #ifdef FML_OS_ANDROID
236  FML_DCHECK(stencil_attachment_config.has_value());
237 #endif // FML_OS_ANDROID
238 
239  RenderTarget target;
240  PixelFormat pixel_format = context.GetCapabilities()->GetDefaultColorFormat();
241  TextureDescriptor color_tex0;
242  color_tex0.storage_mode = color_attachment_config.storage_mode;
243  color_tex0.format = pixel_format;
244  color_tex0.size = size;
245  color_tex0.usage = static_cast<uint64_t>(TextureUsage::kRenderTarget) |
246  static_cast<uint64_t>(TextureUsage::kShaderRead);
247 
248  ColorAttachment color0;
249  color0.clear_color = color_attachment_config.clear_color;
250  color0.load_action = color_attachment_config.load_action;
251  color0.store_action = color_attachment_config.store_action;
252  color0.texture = allocator.CreateTexture(color_tex0);
253 
254  if (!color0.texture) {
255  return {};
256  }
257  color0.texture->SetLabel(SPrintF("%s Color Texture", label.c_str()));
258  target.SetColorAttachment(color0, 0u);
259 
260  if (stencil_attachment_config.has_value()) {
261  target.SetupStencilAttachment(context, allocator, size, false, label,
262  stencil_attachment_config.value());
263  } else {
264  target.SetStencilAttachment(std::nullopt);
265  }
266 
267  return target;
268 }
269 
271  const Context& context,
272  RenderTargetAllocator& allocator,
273  ISize size,
274  const std::string& label,
275  AttachmentConfigMSAA color_attachment_config,
276  std::optional<AttachmentConfig> stencil_attachment_config) {
277  if (size.IsEmpty()) {
278  return {};
279  }
280 
281 // Dont force additional PSO variants on Vulkan.
282 #ifdef FML_OS_ANDROID
283  FML_DCHECK(stencil_attachment_config.has_value());
284 #endif // FML_OS_ANDROID
285 
286  RenderTarget target;
287  PixelFormat pixel_format = context.GetCapabilities()->GetDefaultColorFormat();
288 
289  // Create MSAA color texture.
290 
291  TextureDescriptor color0_tex_desc;
292  color0_tex_desc.storage_mode = color_attachment_config.storage_mode;
293  color0_tex_desc.type = TextureType::kTexture2DMultisample;
294  color0_tex_desc.sample_count = SampleCount::kCount4;
295  color0_tex_desc.format = pixel_format;
296  color0_tex_desc.size = size;
297  color0_tex_desc.usage = static_cast<uint64_t>(TextureUsage::kRenderTarget);
298 
299  auto color0_msaa_tex = allocator.CreateTexture(color0_tex_desc);
300  if (!color0_msaa_tex) {
301  VALIDATION_LOG << "Could not create multisample color texture.";
302  return {};
303  }
304  color0_msaa_tex->SetLabel(
305  SPrintF("%s Color Texture (Multisample)", label.c_str()));
306 
307  // Create color resolve texture.
308 
309  TextureDescriptor color0_resolve_tex_desc;
310  color0_resolve_tex_desc.storage_mode =
311  color_attachment_config.resolve_storage_mode;
312  color0_resolve_tex_desc.format = pixel_format;
313  color0_resolve_tex_desc.size = size;
314  color0_resolve_tex_desc.compression_type = CompressionType::kLossy;
315  color0_resolve_tex_desc.usage =
316  static_cast<uint64_t>(TextureUsage::kRenderTarget) |
317  static_cast<uint64_t>(TextureUsage::kShaderRead);
318 
319  auto color0_resolve_tex = allocator.CreateTexture(color0_resolve_tex_desc);
320  if (!color0_resolve_tex) {
321  VALIDATION_LOG << "Could not create color texture.";
322  return {};
323  }
324  color0_resolve_tex->SetLabel(SPrintF("%s Color Texture", label.c_str()));
325 
326  // Color attachment.
327 
328  ColorAttachment color0;
329  color0.clear_color = color_attachment_config.clear_color;
330  color0.load_action = color_attachment_config.load_action;
331  color0.store_action = color_attachment_config.store_action;
332  color0.texture = color0_msaa_tex;
333  color0.resolve_texture = color0_resolve_tex;
334 
335  target.SetColorAttachment(color0, 0u);
336 
337  // Create MSAA stencil texture.
338 
339  if (stencil_attachment_config.has_value()) {
340  target.SetupStencilAttachment(context, allocator, size, true, label,
341  stencil_attachment_config.value());
342  } else {
343  target.SetStencilAttachment(std::nullopt);
344  }
345 
346  return target;
347 }
348 
350  const Context& context,
351  RenderTargetAllocator& allocator,
352  ISize size,
353  bool msaa,
354  const std::string& label,
355  AttachmentConfig stencil_attachment_config) {
356  TextureDescriptor stencil_tex0;
357  stencil_tex0.storage_mode = stencil_attachment_config.storage_mode;
358  if (msaa) {
360  stencil_tex0.sample_count = SampleCount::kCount4;
361  }
362  stencil_tex0.format = context.GetCapabilities()->GetDefaultStencilFormat();
363  stencil_tex0.size = size;
364  stencil_tex0.usage =
366 
367  StencilAttachment stencil0;
368  stencil0.load_action = stencil_attachment_config.load_action;
369  stencil0.store_action = stencil_attachment_config.store_action;
370  stencil0.clear_stencil = 0u;
371  stencil0.texture = allocator.CreateTexture(stencil_tex0);
372 
373  if (!stencil0.texture) {
374  return; // Error messages are handled by `Allocator::CreateTexture`.
375  }
376  stencil0.texture->SetLabel(SPrintF("%s Stencil Texture", label.c_str()));
377  SetStencilAttachment(std::move(stencil0));
378 }
379 
381  size_t count = 0u;
382  for (const auto& [_, color] : colors_) {
383  if (color.texture) {
384  count++;
385  }
386  if (color.resolve_texture) {
387  count++;
388  }
389  }
390  if (depth_.has_value()) {
391  count++;
392  }
393  if (stencil_.has_value()) {
394  count++;
395  }
396  return count;
397 }
398 
399 std::string RenderTarget::ToString() const {
400  std::stringstream stream;
401 
402  for (const auto& [index, color] : colors_) {
403  stream << SPrintF("Color[%zu]=(%s)", index,
404  ColorAttachmentToString(color).c_str());
405  }
406  if (depth_) {
407  stream << ",";
408  stream << SPrintF("Depth=(%s)",
409  DepthAttachmentToString(depth_.value()).c_str());
410  }
411  if (stencil_) {
412  stream << ",";
413  stream << SPrintF("Stencil=(%s)",
414  StencilAttachmentToString(stencil_.value()).c_str());
415  }
416  return stream.str();
417 }
418 
419 } // namespace impeller
impeller::RenderTarget::SetupStencilAttachment
void SetupStencilAttachment(const Context &context, RenderTargetAllocator &allocator, ISize size, bool msaa, const std::string &label="Offscreen", AttachmentConfig stencil_attachment_config=kDefaultStencilAttachmentConfig)
Definition: render_target.cc:349
impeller::RenderTarget::GetTotalAttachmentCount
size_t GetTotalAttachmentCount() const
Definition: render_target.cc:380
impeller::RenderTarget::AttachmentConfig::store_action
StoreAction store_action
Definition: render_target.h:53
impeller::RenderTarget::AttachmentConfig::load_action
LoadAction load_action
Definition: render_target.h:52
impeller::TextureUsageMask
uint64_t TextureUsageMask
Definition: formats.h:274
impeller::Attachment::store_action
StoreAction store_action
Definition: formats.h:594
impeller::SampleCount
SampleCount
Definition: formats.h:269
impeller::RenderTargetAllocator::Start
virtual void Start()
Mark the beginning of a frame workload.
Definition: render_target.cc:21
impeller::Context::GetCapabilities
virtual const std::shared_ptr< const Capabilities > & GetCapabilities() const =0
Get the capabilities of Impeller context. All optionally supported feature of the platform,...
impeller::ColorAttachment
Definition: formats.h:599
impeller::TextureDescriptor::format
PixelFormat format
Definition: texture_descriptor.h:42
impeller::RenderTarget::SetColorAttachment
RenderTarget & SetColorAttachment(const ColorAttachment &attachment, size_t index)
Definition: render_target.cc:180
impeller::RenderTarget::AttachmentConfigMSAA::store_action
StoreAction store_action
Definition: render_target.h:61
impeller::SampleCount::kCount1
@ kCount1
impeller::TextureUsage::kRenderTarget
@ kRenderTarget
impeller::RenderTarget::GetRenderTargetPixelFormat
PixelFormat GetRenderTargetPixelFormat() const
Definition: render_target.cc:164
impeller::RenderTarget::GetColorAttachmentSize
std::optional< ISize > GetColorAttachmentSize(size_t index) const
Definition: render_target.cc:140
impeller::RenderTargetAllocator::RenderTargetAllocator
RenderTargetAllocator(std::shared_ptr< Allocator > allocator)
Definition: render_target.cc:17
impeller::RenderTarget::GetColorAttachments
const std::map< size_t, ColorAttachment > & GetColorAttachments() const
Definition: render_target.cc:209
impeller::TextureDescriptor::sample_count
SampleCount sample_count
Definition: texture_descriptor.h:47
impeller::RenderTarget::AttachmentConfigMSAA::load_action
LoadAction load_action
Definition: render_target.h:60
validation.h
impeller::TextureDescriptor::usage
TextureUsageMask usage
Definition: texture_descriptor.h:45
impeller::SampleCount::kCount4
@ kCount4
impeller::RenderTarget::AttachmentConfigMSAA::resolve_storage_mode
StorageMode resolve_storage_mode
Definition: render_target.h:59
impeller::RenderTarget::AttachmentConfigMSAA
Definition: render_target.h:57
impeller::RenderTarget::AttachmentConfig
Definition: render_target.h:50
impeller::TextureDescriptor::type
TextureType type
Definition: texture_descriptor.h:41
impeller::TextureType::kTexture2DMultisample
@ kTexture2DMultisample
impeller::StencilAttachment
Definition: formats.h:607
impeller::TSize< int64_t >
impeller::RenderTarget::GetDepthAttachment
const std::optional< DepthAttachment > & GetDepthAttachment() const
Definition: render_target.cc:214
impeller::ColorAttachment::clear_color
Color clear_color
Definition: formats.h:600
impeller::RenderTarget::GetRenderTargetTexture
std::shared_ptr< Texture > GetRenderTargetTexture() const
Definition: render_target.cc:155
impeller::RenderTarget::IterateAllAttachments
void IterateAllAttachments(const std::function< bool(const Attachment &attachment)> &iterator) const
Definition: render_target.cc:105
impeller::RenderTarget::~RenderTarget
~RenderTarget()
impeller::Attachment::texture
std::shared_ptr< Texture > texture
Definition: formats.h:591
impeller::SPrintF
std::string SPrintF(const char *format,...)
Definition: strings.cc:12
impeller::ColorAttachmentToString
std::string ColorAttachmentToString(const ColorAttachment &color)
Definition: formats.cc:123
impeller::TextureUsage::kShaderRead
@ kShaderRead
impeller::PixelFormat::kUnknown
@ kUnknown
impeller::RenderTarget::AttachmentConfig::storage_mode
StorageMode storage_mode
Definition: render_target.h:51
impeller::RenderTargetAllocator::CreateTexture
virtual std::shared_ptr< Texture > CreateTexture(const TextureDescriptor &desc)
Create a new render target texture, or recycle a previously allocated render target texture.
Definition: render_target.cc:25
impeller::Attachment
Definition: formats.h:590
impeller::RenderTarget
Definition: render_target.h:48
impeller::StencilAttachment::clear_stencil
uint32_t clear_stencil
Definition: formats.h:608
impeller::CompressionType::kLossy
@ kLossy
strings.h
impeller::RenderTarget::IsValid
bool IsValid() const
Definition: render_target.cc:34
impeller::RenderTargetAllocator
a wrapper around the impeller [Allocator] instance that can be used to provide caching of allocated r...
Definition: render_target.h:22
impeller::RenderTarget::AttachmentConfig::clear_color
Color clear_color
Definition: render_target.h:54
impeller::RenderTarget::GetRenderTargetSize
ISize GetRenderTargetSize() const
Definition: render_target.cc:150
impeller::TextureDescriptor::size
ISize size
Definition: texture_descriptor.h:43
impeller::RenderTarget::CreateOffscreen
static RenderTarget CreateOffscreen(const Context &context, RenderTargetAllocator &allocator, ISize size, const std::string &label="Offscreen", AttachmentConfig color_attachment_config=kDefaultColorAttachmentConfig, std::optional< AttachmentConfig > stencil_attachment_config=kDefaultStencilAttachmentConfig)
Definition: render_target.cc:223
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:60
allocator.h
impeller::TextureTypeToString
constexpr const char * TextureTypeToString(TextureType type)
Definition: formats.h:243
impeller::Attachment::resolve_texture
std::shared_ptr< Texture > resolve_texture
Definition: formats.h:592
impeller::RenderTarget::AttachmentConfigMSAA::storage_mode
StorageMode storage_mode
Definition: render_target.h:58
impeller::RenderTarget::SetStencilAttachment
RenderTarget & SetStencilAttachment(std::optional< StencilAttachment > attachment)
Definition: render_target.cc:199
impeller::Context
To do anything rendering related with Impeller, you need a context.
Definition: context.h:47
std
Definition: comparable.h:98
impeller::DepthAttachmentToString
std::string DepthAttachmentToString(const DepthAttachment &depth)
Definition: formats.cc:130
impeller::RenderTargetAllocator::End
virtual void End()
Mark the end of a frame workload.
Definition: render_target.cc:23
impeller::Attachment::load_action
LoadAction load_action
Definition: formats.h:593
texture.h
impeller::Attachment::IsValid
bool IsValid() const
Definition: formats.cc:26
context.h
impeller::RenderTarget::GetMaxColorAttacmentBindIndex
size_t GetMaxColorAttacmentBindIndex() const
Definition: render_target.cc:172
impeller::TextureDescriptor::storage_mode
StorageMode storage_mode
Definition: texture_descriptor.h:40
impeller::TextureDescriptor
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
Definition: texture_descriptor.h:39
impeller::TSize::IsEmpty
constexpr bool IsEmpty() const
Definition: size.h:105
render_target.h
impeller::PixelFormat
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition: formats.h:94
impeller::RenderTarget::GetStencilAttachment
const std::optional< StencilAttachment > & GetStencilAttachment() const
Definition: render_target.cc:218
impeller::RenderTarget::SetDepthAttachment
RenderTarget & SetDepthAttachment(std::optional< DepthAttachment > attachment)
Definition: render_target.cc:189
impeller::RenderTarget::GetSampleCount
SampleCount GetSampleCount() const
Definition: render_target.cc:126
impeller::TextureDescriptor::compression_type
CompressionType compression_type
Definition: texture_descriptor.h:48
impeller::RenderTarget::HasColorAttachment
bool HasColorAttachment(size_t index) const
Definition: render_target.cc:133
impeller
Definition: aiks_context.cc:10
impeller::StencilAttachmentToString
std::string StencilAttachmentToString(const StencilAttachment &stencil)
Definition: formats.cc:137
impeller::RenderTarget::ToString
std::string ToString() const
Definition: render_target.cc:399
impeller::RenderTarget::CreateOffscreenMSAA
static RenderTarget CreateOffscreenMSAA(const Context &context, RenderTargetAllocator &allocator, ISize size, const std::string &label="Offscreen MSAA", AttachmentConfigMSAA color_attachment_config=kDefaultColorAttachmentConfigMSAA, std::optional< AttachmentConfig > stencil_attachment_config=kDefaultStencilAttachmentConfig)
Definition: render_target.cc:270
impeller::RenderTarget::AttachmentConfigMSAA::clear_color
Color clear_color
Definition: render_target.h:62
impeller::RenderTarget::RenderTarget
RenderTarget()