Skip to content

Commit cf8eaa6

Browse files
Jonah Williamsgaaclarke
authored andcommitted
[Impeller] Cache render target texture allocations across frames. (flutter#44527)
When allocating a non-host visible texture for a render target, the allocator will hold onto a reference to this texture descriptor. On the immediate next frame, this texture is made available to replace requested allocations for new render target textures. if this texture is not used, then at the end of the next frame it is discarded. This removes the vast majority of allocations in most flutter gallery and wonderous. This does not attempt to use different sized textures for the cache. There are two caveats noted in the PR contents. Fixes flutter/flutter#131515
1 parent 824bb0d commit cf8eaa6

25 files changed

+432
-38
lines changed

ci/licenses_golden/excluded_files

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,12 +128,14 @@
128128
../../../flutter/impeller/compiler/README.md
129129
../../../flutter/impeller/compiler/compiler_unittests.cc
130130
../../../flutter/impeller/compiler/switches_unittests.cc
131+
../../../flutter/impeller/core/allocator_unittests.cc
131132
../../../flutter/impeller/display_list/dl_unittests.cc
132133
../../../flutter/impeller/display_list/skia_conversions_unittests.cc
133134
../../../flutter/impeller/docs
134135
../../../flutter/impeller/entity/contents/filters/inputs/filter_input_unittests.cc
135136
../../../flutter/impeller/entity/entity_unittests.cc
136137
../../../flutter/impeller/entity/geometry/geometry_unittests.cc
138+
../../../flutter/impeller/entity/render_target_cache_unittests.cc
137139
../../../flutter/impeller/fixtures
138140
../../../flutter/impeller/geometry/README.md
139141
../../../flutter/impeller/geometry/geometry_unittests.cc

ci/licenses_golden/licenses_flutter

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1271,6 +1271,8 @@ ORIGIN: ../../../flutter/impeller/entity/geometry/vertices_geometry.cc + ../../.
12711271
ORIGIN: ../../../flutter/impeller/entity/geometry/vertices_geometry.h + ../../../flutter/LICENSE
12721272
ORIGIN: ../../../flutter/impeller/entity/inline_pass_context.cc + ../../../flutter/LICENSE
12731273
ORIGIN: ../../../flutter/impeller/entity/inline_pass_context.h + ../../../flutter/LICENSE
1274+
ORIGIN: ../../../flutter/impeller/entity/render_target_cache.cc + ../../../flutter/LICENSE
1275+
ORIGIN: ../../../flutter/impeller/entity/render_target_cache.h + ../../../flutter/LICENSE
12741276
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/advanced_blend.glsl + ../../../flutter/LICENSE
12751277
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/advanced_blend.vert + ../../../flutter/LICENSE
12761278
ORIGIN: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_color.frag + ../../../flutter/LICENSE
@@ -3994,6 +3996,8 @@ FILE: ../../../flutter/impeller/entity/geometry/vertices_geometry.cc
39943996
FILE: ../../../flutter/impeller/entity/geometry/vertices_geometry.h
39953997
FILE: ../../../flutter/impeller/entity/inline_pass_context.cc
39963998
FILE: ../../../flutter/impeller/entity/inline_pass_context.h
3999+
FILE: ../../../flutter/impeller/entity/render_target_cache.cc
4000+
FILE: ../../../flutter/impeller/entity/render_target_cache.h
39974001
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend.glsl
39984002
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend.vert
39994003
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_color.frag

impeller/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ impeller_component("impeller_unittests") {
7777
"base:base_unittests",
7878
"blobcat:blobcat_unittests",
7979
"compiler:compiler_unittests",
80+
"core:allocator_unittests",
8081
"display_list:skia_conversions_unittests",
8182
"geometry:geometry_unittests",
8283
"runtime_stage:runtime_stage_unittests",
@@ -89,6 +90,7 @@ impeller_component("impeller_unittests") {
8990
"aiks:aiks_unittests",
9091
"display_list:display_list_unittests",
9192
"entity:entity_unittests",
93+
"entity:render_target_cache_unittests",
9294
"fixtures",
9395
"geometry:geometry_unittests",
9496
"image:image_unittests",

impeller/aiks/picture.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,15 @@ std::shared_ptr<Texture> Picture::RenderToTexture(
5454
// This texture isn't host visible, but we might want to add host visible
5555
// features to Image someday.
5656
auto impeller_context = context.GetContext();
57+
// Do not use the render target cache as the lifecycle of this texture
58+
// will outlive a particular frame.
59+
RenderTargetAllocator render_target_allocator =
60+
RenderTargetAllocator(impeller_context->GetResourceAllocator());
5761
RenderTarget target;
5862
if (impeller_context->GetCapabilities()->SupportsOffscreenMSAA()) {
5963
target = RenderTarget::CreateOffscreenMSAA(
6064
*impeller_context, // context
65+
render_target_allocator, // allocator
6166
size, // size
6267
"Picture Snapshot MSAA", // label
6368
RenderTarget::
@@ -70,6 +75,7 @@ std::shared_ptr<Texture> Picture::RenderToTexture(
7075
} else {
7176
target = RenderTarget::CreateOffscreen(
7277
*impeller_context, // context
78+
render_target_allocator, // allocator
7379
size, // size
7480
"Picture Snapshot", // label
7581
RenderTarget::kDefaultColorAttachmentConfig // color_attachment_config

impeller/core/BUILD.gn

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,15 @@ impeller_component("core") {
4949
"//flutter/fml",
5050
]
5151
}
52+
53+
impeller_component("allocator_unittests") {
54+
testonly = true
55+
56+
sources = [ "allocator_unittests.cc" ]
57+
58+
deps = [
59+
":core",
60+
"../geometry",
61+
"//flutter/testing:testing_lib",
62+
]
63+
}

impeller/core/allocator.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include "impeller/base/validation.h"
88
#include "impeller/core/device_buffer.h"
9+
#include "impeller/core/formats.h"
910
#include "impeller/core/range.h"
1011

1112
namespace impeller {
@@ -57,10 +58,10 @@ std::shared_ptr<Texture> Allocator::CreateTexture(
5758
return OnCreateTexture(desc);
5859
}
5960

61+
void Allocator::DidAcquireSurfaceFrame() {}
62+
6063
uint16_t Allocator::MinimumBytesPerRow(PixelFormat format) const {
6164
return BytesPerPixelForPixelFormat(format);
6265
}
6366

64-
void Allocator::DidAcquireSurfaceFrame() {}
65-
6667
} // namespace impeller

impeller/core/allocator.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
#include "flutter/fml/macros.h"
1010
#include "flutter/fml/mapping.h"
1111
#include "impeller/core/device_buffer_descriptor.h"
12+
#include "impeller/core/texture.h"
1213
#include "impeller/core/texture_descriptor.h"
14+
#include "impeller/geometry/size.h"
1315

1416
namespace impeller {
1517

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
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 <memory>
6+
#include "flutter/testing/testing.h"
7+
#include "impeller/core/allocator.h"
8+
#include "impeller/core/formats.h"
9+
#include "impeller/core/texture_descriptor.h"
10+
#include "impeller/geometry/size.h"
11+
#include "impeller/renderer/testing/mocks.h"
12+
13+
namespace impeller {
14+
namespace testing {
15+
16+
TEST(AllocatorTest, TextureDescriptorCompatibility) {
17+
// Size.
18+
{
19+
TextureDescriptor desc_a = {.size = ISize(100, 100)};
20+
TextureDescriptor desc_b = {.size = ISize(100, 100)};
21+
TextureDescriptor desc_c = {.size = ISize(101, 100)};
22+
23+
ASSERT_EQ(desc_a, desc_b);
24+
ASSERT_NE(desc_a, desc_c);
25+
}
26+
// Storage Mode.
27+
{
28+
TextureDescriptor desc_a = {.storage_mode = StorageMode::kDevicePrivate};
29+
TextureDescriptor desc_b = {.storage_mode = StorageMode::kDevicePrivate};
30+
TextureDescriptor desc_c = {.storage_mode = StorageMode::kHostVisible};
31+
32+
ASSERT_EQ(desc_a, desc_b);
33+
ASSERT_NE(desc_a, desc_c);
34+
}
35+
// Format.
36+
{
37+
TextureDescriptor desc_a = {.format = PixelFormat::kR8G8B8A8UNormInt};
38+
TextureDescriptor desc_b = {.format = PixelFormat::kR8G8B8A8UNormInt};
39+
TextureDescriptor desc_c = {.format = PixelFormat::kB10G10R10A10XR};
40+
41+
ASSERT_EQ(desc_a, desc_b);
42+
ASSERT_NE(desc_a, desc_c);
43+
}
44+
// Sample Count.
45+
{
46+
TextureDescriptor desc_a = {.sample_count = SampleCount::kCount4};
47+
TextureDescriptor desc_b = {.sample_count = SampleCount::kCount4};
48+
TextureDescriptor desc_c = {.sample_count = SampleCount::kCount1};
49+
50+
ASSERT_EQ(desc_a, desc_b);
51+
ASSERT_NE(desc_a, desc_c);
52+
}
53+
// Sample Count.
54+
{
55+
TextureDescriptor desc_a = {.type = TextureType::kTexture2DMultisample};
56+
TextureDescriptor desc_b = {.type = TextureType::kTexture2DMultisample};
57+
TextureDescriptor desc_c = {.type = TextureType::kTexture2D};
58+
59+
ASSERT_EQ(desc_a, desc_b);
60+
ASSERT_NE(desc_a, desc_c);
61+
}
62+
// Compression.
63+
{
64+
TextureDescriptor desc_a = {.compression_type = CompressionType::kLossless};
65+
TextureDescriptor desc_b = {.compression_type = CompressionType::kLossless};
66+
TextureDescriptor desc_c = {.compression_type = CompressionType::kLossy};
67+
68+
ASSERT_EQ(desc_a, desc_b);
69+
ASSERT_NE(desc_a, desc_c);
70+
}
71+
// Mip Count.
72+
{
73+
TextureDescriptor desc_a = {.mip_count = 1};
74+
TextureDescriptor desc_b = {.mip_count = 1};
75+
TextureDescriptor desc_c = {.mip_count = 4};
76+
77+
ASSERT_EQ(desc_a, desc_b);
78+
ASSERT_NE(desc_a, desc_c);
79+
}
80+
}
81+
82+
} // namespace testing
83+
} // namespace impeller

impeller/core/texture_descriptor.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,21 @@ struct TextureDescriptor {
6666
return IsMultisampleCapable(type) ? count > 1 : count == 1;
6767
}
6868

69+
constexpr bool operator==(const TextureDescriptor& other) const {
70+
return size == other.size && //
71+
storage_mode == other.storage_mode && //
72+
format == other.format && //
73+
usage == other.usage && //
74+
sample_count == other.sample_count && //
75+
type == other.type && //
76+
compression_type == other.compression_type && //
77+
mip_count == other.mip_count;
78+
}
79+
80+
constexpr bool operator!=(const TextureDescriptor& other) const {
81+
return !(*this == other);
82+
}
83+
6984
constexpr bool IsValid() const {
7085
return format != PixelFormat::kUnknown && //
7186
size.IsPositive() && //

impeller/entity/BUILD.gn

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,8 @@ impeller_component("entity") {
243243
"geometry/vertices_geometry.h",
244244
"inline_pass_context.cc",
245245
"inline_pass_context.h",
246+
"render_target_cache.cc",
247+
"render_target_cache.h",
246248
]
247249

248250
if (impeller_debug) {
@@ -283,3 +285,14 @@ impeller_component("entity_unittests") {
283285
"../playground:playground_test",
284286
]
285287
}
288+
289+
impeller_component("render_target_cache_unittests") {
290+
testonly = true
291+
292+
sources = [ "render_target_cache_unittests.cc" ]
293+
294+
deps = [
295+
":entity",
296+
"//flutter/testing:testing_lib",
297+
]
298+
}

0 commit comments

Comments
 (0)