| 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
5 #include "impeller/renderer/render_target.h"
6
7 #include <sstream>
8
9 #include "impeller/base/strings.h"
10 #include "impeller/base/validation.h"
11 #include "impeller/core/allocator.h"
12 #include "impeller/core/texture.h"
13 #include "impeller/renderer/context.h"
14
15 namespace impeller {
16
17 RenderTargetAllocator::RenderTargetAllocator(
18 std::shared_ptr<Allocator> allocator)
19 : allocator_(std::move(allocator)) {}
20
21 void RenderTargetAllocator::Start() {}
22
23 void RenderTargetAllocator::End() {}
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)) {
37 VALIDATION_LOG
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) {
58 VALIDATION_LOG
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()) << " != "
79 << TextureTypeToString(
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
105 void RenderTarget::IterateAllAttachments(
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
126 SampleCount RenderTarget::GetSampleCount() const {
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
150 ISize RenderTarget::GetRenderTargetSize() const {
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
164 PixelFormat RenderTarget::GetRenderTargetPixelFormat() const {
165 if (auto texture = GetRenderTargetTexture(); texture != nullptr) {
166 return texture->GetTextureDescriptor().format;
167 }
168
169 return PixelFormat::kUnknown;
170 }
171
172 size_t RenderTarget::GetMaxColorAttacmentBindIndex() const {
173 size_t max = 0;
174 for (const auto& color : colors_) {
175 max = std::max(color.first, max);
176 }
177 return max;
178 }
179
180 RenderTarget& RenderTarget::SetColorAttachment(
181 const ColorAttachment& attachment,
182 size_t index) {
183 if (attachment.IsValid()) {
184 colors_[index] = attachment;
185 }
186 return *this;
187 }
188
189 RenderTarget& RenderTarget::SetDepthAttachment(
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
199 RenderTarget& RenderTarget::SetStencilAttachment(
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
223 RenderTarget RenderTarget::CreateOffscreen(
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
270 RenderTarget RenderTarget::CreateOffscreenMSAA(
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
349 void RenderTarget::SetupStencilAttachment(
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) {
359 stencil_tex0.type = TextureType::kTexture2DMultisample;
360 stencil_tex0.sample_count = SampleCount::kCount4;
361 }
362 stencil_tex0.format = context.GetCapabilities()->GetDefaultStencilFormat();
363 stencil_tex0.size = size;
364 stencil_tex0.usage =
365 static_cast<TextureUsageMask>(TextureUsage::kRenderTarget);
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
380 size_t RenderTarget::GetTotalAttachmentCount() const {
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()