Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 1f7f37e

Browse files
author
Jonah Williams
authored
[Impeller] avoid heap allocation in RenderTarget object. (#56829)
All render targets created by flutter have a single color attachment. Lets specialize that case in impeller::RenderTarget by creating a field for that attachment description instead of placing it in a hashmap.
1 parent c7e3d55 commit 1f7f37e

21 files changed

Lines changed: 290 additions & 170 deletions

impeller/display_list/canvas.cc

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "flutter/fml/logging.h"
1515
#include "flutter/fml/trace_event.h"
1616
#include "impeller/base/validation.h"
17+
#include "impeller/core/formats.h"
1718
#include "impeller/display_list/color_filter.h"
1819
#include "impeller/display_list/image_filter.h"
1920
#include "impeller/display_list/skia_conversions.h"
@@ -853,7 +854,7 @@ void Canvas::DrawAtlas(const std::shared_ptr<AtlasContents>& atlas_contents,
853854

854855
void Canvas::SetupRenderPass() {
855856
renderer_.GetRenderTargetCache()->Start();
856-
auto color0 = render_target_.GetColorAttachments().find(0u)->second;
857+
ColorAttachment color0 = render_target_.GetColorAttachment(0);
857858

858859
auto& stencil_attachment = render_target_.GetStencilAttachment();
859860
auto& depth_attachment = render_target_.GetDepthAttachment();
@@ -1460,8 +1461,7 @@ void Canvas::AddRenderEntityToCurrentPass(Entity& entity, bool reuse_depth) {
14601461
RenderTarget& render_target = render_passes_.back()
14611462
.inline_pass_context->GetPassTarget()
14621463
.GetRenderTarget();
1463-
ColorAttachment attachment =
1464-
render_target.GetColorAttachments().find(0u)->second;
1464+
ColorAttachment attachment = render_target.GetColorAttachment(0);
14651465
// Attachment.clear color needs to be premultiplied at all times, but the
14661466
// Color::Blend function requires unpremultiplied colors.
14671467
attachment.clear_color = attachment.clear_color.Unpremultiply()
@@ -1588,8 +1588,7 @@ std::shared_ptr<Texture> Canvas::FlipBackdrop(Point global_pass_position,
15881588
}
15891589

15901590
if (should_use_onscreen) {
1591-
ColorAttachment color0 =
1592-
render_target_.GetColorAttachments().find(0u)->second;
1591+
ColorAttachment color0 = render_target_.GetColorAttachment(0);
15931592
// When MSAA is being used, we end up overriding the entire backdrop by
15941593
// drawing the previous pass texture, and so we don't have to clear it and
15951594
// can use kDontCare.

impeller/entity/entity_pass_target.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ EntityPassTarget::EntityPassTarget(const RenderTarget& render_target,
1919

2020
std::shared_ptr<Texture> EntityPassTarget::Flip(
2121
const ContentContext& renderer) {
22-
auto color0 = target_.GetColorAttachments().find(0)->second;
22+
ColorAttachment color0 = target_.GetColorAttachment(0);
2323
if (!color0.resolve_texture) {
2424
VALIDATION_LOG << "EntityPassTarget Flip should never be called for a "
2525
"non-MSAA target.";

impeller/entity/entity_pass_target_unittests.cc

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,14 @@ TEST_P(EntityPassTargetTest, SwapWithMSAATexture) {
3131

3232
auto entity_pass_target = EntityPassTarget(render_target, false, false);
3333

34-
auto color0 = entity_pass_target.GetRenderTarget()
35-
.GetColorAttachments()
36-
.find(0u)
37-
->second;
34+
auto color0 = entity_pass_target.GetRenderTarget().GetColorAttachment(0);
3835
auto msaa_tex = color0.texture;
3936
auto resolve_tex = color0.resolve_texture;
4037

4138
FML_DCHECK(content_context);
4239
entity_pass_target.Flip(*content_context);
4340

44-
color0 = entity_pass_target.GetRenderTarget()
45-
.GetColorAttachments()
46-
.find(0u)
47-
->second;
41+
color0 = entity_pass_target.GetRenderTarget().GetColorAttachment(0);
4842

4943
ASSERT_EQ(msaa_tex, color0.texture);
5044
ASSERT_NE(resolve_tex, color0.resolve_texture);
@@ -89,10 +83,7 @@ TEST_P(EntityPassTargetTest, SwapWithMSAAImplicitResolve) {
8983

9084
auto entity_pass_target = EntityPassTarget(render_target, false, true);
9185

92-
auto color0 = entity_pass_target.GetRenderTarget()
93-
.GetColorAttachments()
94-
.find(0u)
95-
->second;
86+
auto color0 = entity_pass_target.GetRenderTarget().GetColorAttachment(0);
9687
auto msaa_tex = color0.texture;
9788
auto resolve_tex = color0.resolve_texture;
9889

@@ -101,10 +92,7 @@ TEST_P(EntityPassTargetTest, SwapWithMSAAImplicitResolve) {
10192
FML_DCHECK(content_context);
10293
entity_pass_target.Flip(*content_context);
10394

104-
color0 = entity_pass_target.GetRenderTarget()
105-
.GetColorAttachments()
106-
.find(0u)
107-
->second;
95+
color0 = entity_pass_target.GetRenderTarget().GetColorAttachment(0);
10896

10997
ASSERT_NE(msaa_tex, color0.texture);
11098
ASSERT_NE(resolve_tex, color0.resolve_texture);

impeller/entity/inline_pass_context.cc

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -86,29 +86,21 @@ const std::shared_ptr<RenderPass>& InlinePassContext::GetRenderPass() {
8686
return pass_;
8787
}
8888

89-
if (pass_target_.GetRenderTarget().GetColorAttachments().empty()) {
90-
VALIDATION_LOG << "Color attachment unexpectedly missing from the "
91-
"EntityPass render target.";
92-
return pass_;
93-
}
94-
9589
command_buffer_->SetLabel("EntityPass Command Buffer");
9690

9791
{
9892
// If the pass target has a resolve texture, then we're using MSAA.
99-
bool is_msaa = pass_target_.GetRenderTarget()
100-
.GetColorAttachments()
101-
.find(0)
102-
->second.resolve_texture != nullptr;
93+
bool is_msaa =
94+
pass_target_.GetRenderTarget().GetColorAttachment(0).resolve_texture !=
95+
nullptr;
10396
if (pass_count_ > 0 && is_msaa) {
10497
pass_target_.Flip(renderer_);
10598
}
10699
}
107100

108101
// Find the color attachment a second time, since the target may have just
109102
// flipped.
110-
auto color0 =
111-
pass_target_.GetRenderTarget().GetColorAttachments().find(0)->second;
103+
ColorAttachment color0 = pass_target_.GetRenderTarget().GetColorAttachment(0);
112104
bool is_msaa = color0.resolve_texture != nullptr;
113105

114106
if (pass_count_ > 0) {

impeller/entity/render_target_cache.cc

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// found in the LICENSE file.
44

55
#include "impeller/entity/render_target_cache.h"
6+
#include "impeller/core/formats.h"
67
#include "impeller/renderer/render_target.h"
78

89
namespace impeller {
@@ -52,10 +53,10 @@ RenderTarget RenderTargetCache::CreateOffscreen(
5253
const auto other_config = render_target_data.config;
5354
if (!render_target_data.used_this_frame && other_config == config) {
5455
render_target_data.used_this_frame = true;
55-
auto color0 = render_target_data.render_target.GetColorAttachments()
56-
.find(0u)
57-
->second;
58-
auto depth = render_target_data.render_target.GetDepthAttachment();
56+
ColorAttachment color0 =
57+
render_target_data.render_target.GetColorAttachment(0);
58+
std::optional<DepthAttachment> depth =
59+
render_target_data.render_target.GetDepthAttachment();
5960
std::shared_ptr<Texture> depth_tex = depth ? depth->texture : nullptr;
6061
return RenderTargetAllocator::CreateOffscreen(
6162
context, size, mip_count, label, color_attachment_config,
@@ -102,10 +103,10 @@ RenderTarget RenderTargetCache::CreateOffscreenMSAA(
102103
const auto other_config = render_target_data.config;
103104
if (!render_target_data.used_this_frame && other_config == config) {
104105
render_target_data.used_this_frame = true;
105-
auto color0 = render_target_data.render_target.GetColorAttachments()
106-
.find(0u)
107-
->second;
108-
auto depth = render_target_data.render_target.GetDepthAttachment();
106+
ColorAttachment color0 =
107+
render_target_data.render_target.GetColorAttachment(0);
108+
std::optional<DepthAttachment> depth =
109+
render_target_data.render_target.GetDepthAttachment();
109110
std::shared_ptr<Texture> depth_tex = depth ? depth->texture : nullptr;
110111
return RenderTargetAllocator::CreateOffscreenMSAA(
111112
context, size, mip_count, label, color_attachment_config,

impeller/entity/render_target_cache_unittests.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "flutter/testing/testing.h"
88
#include "impeller/base/validation.h"
99
#include "impeller/core/allocator.h"
10+
#include "impeller/core/formats.h"
1011
#include "impeller/core/texture_descriptor.h"
1112
#include "impeller/entity/entity_playground.h"
1213
#include "impeller/entity/render_target_cache.h"
@@ -104,8 +105,8 @@ TEST_P(RenderTargetCacheTest, CachedTextureGetsNewAttachmentConfig) {
104105
*GetContext(), {100, 100}, 1, "Offscreen2", color_attachment_config);
105106
render_target_cache.End();
106107

107-
auto color1 = target1.GetColorAttachments().find(0)->second;
108-
auto color2 = target2.GetColorAttachments().find(0)->second;
108+
ColorAttachment color1 = target1.GetColorAttachment(0);
109+
ColorAttachment color2 = target2.GetColorAttachment(0);
109110
// The second color attachment should reuse the first attachment's texture
110111
// but with attributes from the second AttachmentConfig.
111112
EXPECT_EQ(color2.texture, color1.texture);

impeller/playground/playground.cc

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -284,20 +284,14 @@ bool Playground::OpenPlaygroundHere(
284284
}
285285
buffer->SetLabel("ImGui Command Buffer");
286286

287-
if (render_target.GetColorAttachments().empty()) {
288-
VALIDATION_LOG << "render target attachments are empty.";
289-
return false;
290-
}
291-
292-
auto color0 = render_target.GetColorAttachments().find(0)->second;
287+
auto color0 = render_target.GetColorAttachment(0);
293288
color0.load_action = LoadAction::kLoad;
294289
if (color0.resolve_texture) {
295290
color0.texture = color0.resolve_texture;
296291
color0.resolve_texture = nullptr;
297292
color0.store_action = StoreAction::kStore;
298293
}
299294
render_target.SetColorAttachment(color0, 0);
300-
301295
render_target.SetStencilAttachment(std::nullopt);
302296
render_target.SetDepthAttachment(std::nullopt);
303297

impeller/renderer/backend/gles/render_pass_gles.cc

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "fml/closure.h"
1212
#include "fml/logging.h"
1313
#include "impeller/base/validation.h"
14+
#include "impeller/core/formats.h"
1415
#include "impeller/renderer/backend/gles/context_gles.h"
1516
#include "impeller/renderer/backend/gles/device_buffer_gles.h"
1617
#include "impeller/renderer/backend/gles/formats_gles.h"
@@ -550,9 +551,11 @@ bool RenderPassGLES::OnEncodeCommands(const Context& context) const {
550551
if (!render_target.HasColorAttachment(0u)) {
551552
return false;
552553
}
553-
const auto& color0 = render_target.GetColorAttachments().at(0u);
554-
const auto& depth0 = render_target.GetDepthAttachment();
555-
const auto& stencil0 = render_target.GetStencilAttachment();
554+
const ColorAttachment& color0 = render_target.GetColorAttachment(0);
555+
const std::optional<DepthAttachment>& depth0 =
556+
render_target.GetDepthAttachment();
557+
const std::optional<StencilAttachment>& stencil0 =
558+
render_target.GetStencilAttachment();
556559

557560
auto pass_data = std::make_shared<RenderPassData>();
558561
pass_data->label = label_;

impeller/renderer/backend/gles/test/surface_gles_unittests.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ TEST_P(SurfaceGLESTest, CanWrapNonZeroFBO) {
2222
ASSERT_TRUE(surface->IsValid());
2323
ASSERT_TRUE(surface->GetRenderTarget().HasColorAttachment(0));
2424
const auto& texture = TextureGLES::Cast(
25-
*(surface->GetRenderTarget().GetColorAttachments().at(0).texture));
25+
*(surface->GetRenderTarget().GetColorAttachment(0).texture));
2626
auto wrapped = texture.GetFBO();
2727
ASSERT_TRUE(wrapped.has_value());
2828
// NOLINTNEXTLINE(bugprone-unchecked-optional-access)

impeller/renderer/backend/metal/render_pass_mtl.mm

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -104,15 +104,15 @@ static bool ConfigureStencilAttachment(
104104
const RenderTarget& desc) {
105105
auto result = [MTLRenderPassDescriptor renderPassDescriptor];
106106

107-
const auto& colors = desc.GetColorAttachments();
108-
109-
for (const auto& color : colors) {
110-
if (!ConfigureColorAttachment(color.second,
111-
result.colorAttachments[color.first])) {
112-
VALIDATION_LOG << "Could not configure color attachment at index "
113-
<< color.first;
114-
return nil;
115-
}
107+
bool configured_attachment = desc.IterateAllColorAttachments(
108+
[&result](size_t index, const ColorAttachment& attachment) -> bool {
109+
return ConfigureColorAttachment(attachment,
110+
result.colorAttachments[index]);
111+
});
112+
113+
if (!configured_attachment) {
114+
VALIDATION_LOG << "Could not configure color attachments";
115+
return nil;
116116
}
117117

118118
const auto& depth = desc.GetDepthAttachment();

0 commit comments

Comments
 (0)