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

Commit 5574bf5

Browse files
author
Jonah Williams
authored
[Impeller] Cache entire render target and not just allocations. (#50990)
This may be required to fix flutter/flutter#144116 , and in general the safety of the render pass caches. Because the RenderPass / Framebuffer objects refer to specific attachments, the caches are placed on the resolve texture, which is "real". The stencil/depth and or MSAA textures may be different but that didn't seem to matter on many Android devices. It doesn't seem like its actually valid though, whether or not there is a validation error to catch it. I can confirm this fixes flutter/flutter#144116 locally. This change moves the cache one level up to cover the properties of the RenderTarget we care about, and ensures that we always use the same attachment combinations. Fixes flutter/flutter#141750 Maybe flutter/flutter#144255 ?
1 parent ea6adb0 commit 5574bf5

19 files changed

+387
-297
lines changed

impeller/aiks/aiks_unittests.cc

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3348,10 +3348,9 @@ TEST_P(AiksTest, GaussianBlurAllocatesCorrectMipCountRenderTarget) {
33483348
picture.ToImage(aiks_context, {100, 100});
33493349

33503350
size_t max_mip_count = 0;
3351-
for (auto it = cache->GetTextureDataBegin(); it != cache->GetTextureDataEnd();
3352-
++it) {
3353-
max_mip_count =
3354-
std::max(it->texture->GetTextureDescriptor().mip_count, max_mip_count);
3351+
for (auto it = cache->GetRenderTargetDataBegin();
3352+
it != cache->GetRenderTargetDataEnd(); ++it) {
3353+
max_mip_count = std::max(it->config.mip_count, max_mip_count);
33553354
}
33563355
EXPECT_EQ(max_mip_count, blur_required_mip_count);
33573356
}
@@ -3378,10 +3377,9 @@ TEST_P(AiksTest, GaussianBlurMipMapNestedLayer) {
33783377
picture.ToImage(aiks_context, {100, 100});
33793378

33803379
size_t max_mip_count = 0;
3381-
for (auto it = cache->GetTextureDataBegin(); it != cache->GetTextureDataEnd();
3382-
++it) {
3383-
max_mip_count =
3384-
std::max(it->texture->GetTextureDescriptor().mip_count, max_mip_count);
3380+
for (auto it = cache->GetRenderTargetDataBegin();
3381+
it != cache->GetRenderTargetDataEnd(); ++it) {
3382+
max_mip_count = std::max(it->config.mip_count, max_mip_count);
33853383
}
33863384
EXPECT_EQ(max_mip_count, blur_required_mip_count);
33873385
// The log is FML_DLOG, so only check in debug builds.
@@ -3414,10 +3412,9 @@ TEST_P(AiksTest, GaussianBlurMipMapImageFilter) {
34143412
picture.ToImage(aiks_context, {1024, 768});
34153413

34163414
size_t max_mip_count = 0;
3417-
for (auto it = cache->GetTextureDataBegin(); it != cache->GetTextureDataEnd();
3418-
++it) {
3419-
max_mip_count =
3420-
std::max(it->texture->GetTextureDescriptor().mip_count, max_mip_count);
3415+
for (auto it = cache->GetRenderTargetDataBegin();
3416+
it != cache->GetRenderTargetDataEnd(); ++it) {
3417+
max_mip_count = std::max(it->config.mip_count, max_mip_count);
34213418
}
34223419
EXPECT_EQ(max_mip_count, blur_required_mip_count);
34233420
// The log is FML_DLOG, so only check in debug builds.
@@ -3456,10 +3453,9 @@ TEST_P(AiksTest, GaussianBlurMipMapSolidColor) {
34563453
picture.ToImage(aiks_context, {1024, 768});
34573454

34583455
size_t max_mip_count = 0;
3459-
for (auto it = cache->GetTextureDataBegin(); it != cache->GetTextureDataEnd();
3460-
++it) {
3461-
max_mip_count =
3462-
std::max(it->texture->GetTextureDescriptor().mip_count, max_mip_count);
3456+
for (auto it = cache->GetRenderTargetDataBegin();
3457+
it != cache->GetRenderTargetDataEnd(); ++it) {
3458+
max_mip_count = std::max(it->config.mip_count, max_mip_count);
34633459
}
34643460
EXPECT_EQ(max_mip_count, blur_required_mip_count);
34653461
// The log is FML_DLOG, so only check in debug builds.

impeller/aiks/picture.cc

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,21 +60,19 @@ std::shared_ptr<Texture> Picture::RenderToTexture(
6060
RenderTargetAllocator(impeller_context->GetResourceAllocator());
6161
RenderTarget target;
6262
if (impeller_context->GetCapabilities()->SupportsOffscreenMSAA()) {
63-
target = RenderTarget::CreateOffscreenMSAA(
64-
*impeller_context, // context
65-
render_target_allocator, // allocator
66-
size, // size
63+
target = render_target_allocator.CreateOffscreenMSAA(
64+
*impeller_context, // context
65+
size, // size
6766
/*mip_count=*/1,
6867
"Picture Snapshot MSAA", // label
6968
RenderTarget::
7069
kDefaultColorAttachmentConfigMSAA, // color_attachment_config
7170
std::nullopt // stencil_attachment_config
7271
);
7372
} else {
74-
target = RenderTarget::CreateOffscreen(
75-
*impeller_context, // context
76-
render_target_allocator, // allocator
77-
size, // size
73+
target = render_target_allocator.CreateOffscreen(
74+
*impeller_context, // context
75+
size, // size
7876
/*mip_count=*/1,
7977
"Picture Snapshot", // label
8078
RenderTarget::kDefaultColorAttachmentConfig, // color_attachment_config

impeller/entity/contents/checkerboard_contents_unittests.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ TEST_P(EntityTest, RendersWithoutError) {
3434

3535
auto content_context = GetContentContext();
3636
auto buffer = content_context->GetContext()->CreateCommandBuffer();
37-
auto render_target = RenderTarget::CreateOffscreenMSAA(
38-
*content_context->GetContext(),
39-
*GetContentContext()->GetRenderTargetCache(), {100, 100},
40-
/*mip_count=*/1);
37+
auto render_target =
38+
GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
39+
*content_context->GetContext(), {100, 100},
40+
/*mip_count=*/1);
4141
auto render_pass = buffer->CreateRenderPass(render_target);
4242
auto recording_pass = std::make_shared<RecordingRenderPass>(
4343
render_pass, GetContext(), render_target);

impeller/entity/contents/content_context.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -490,13 +490,13 @@ fml::StatusOr<RenderTarget> ContentContext::MakeSubpass(
490490
: std::optional<RenderTarget::AttachmentConfig>();
491491

492492
if (context->GetCapabilities()->SupportsOffscreenMSAA() && msaa_enabled) {
493-
subpass_target = RenderTarget::CreateOffscreenMSAA(
494-
*context, *GetRenderTargetCache(), texture_size,
493+
subpass_target = GetRenderTargetCache()->CreateOffscreenMSAA(
494+
*context, texture_size,
495495
/*mip_count=*/mip_count, SPrintF("%s Offscreen", label.c_str()),
496496
RenderTarget::kDefaultColorAttachmentConfigMSAA, depth_stencil_config);
497497
} else {
498-
subpass_target = RenderTarget::CreateOffscreen(
499-
*context, *GetRenderTargetCache(), texture_size,
498+
subpass_target = GetRenderTargetCache()->CreateOffscreen(
499+
*context, texture_size,
500500
/*mip_count=*/mip_count, SPrintF("%s Offscreen", label.c_str()),
501501
RenderTarget::kDefaultColorAttachmentConfig, depth_stencil_config);
502502
}

impeller/entity/contents/scene_contents.cc

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,8 @@ bool SceneContents::Render(const ContentContext& renderer,
4646

4747
RenderTarget subpass_target;
4848
if (renderer.GetContext()->GetCapabilities()->SupportsOffscreenMSAA()) {
49-
subpass_target = RenderTarget::CreateOffscreenMSAA(
49+
subpass_target = renderer.GetRenderTargetCache()->CreateOffscreenMSAA(
5050
*renderer.GetContext(), // context
51-
*renderer.GetRenderTargetCache(), // allocator
5251
ISize(coverage.value().GetSize()), // size
5352
/*mip_count=*/1,
5453
"SceneContents", // label
@@ -65,9 +64,8 @@ bool SceneContents::Render(const ContentContext& renderer,
6564
} // stencil_attachment_config
6665
);
6766
} else {
68-
subpass_target = RenderTarget::CreateOffscreen(
67+
subpass_target = renderer.GetRenderTargetCache()->CreateOffscreen(
6968
*renderer.GetContext(), // context
70-
*renderer.GetRenderTargetCache(), // allocator
7169
ISize(coverage.value().GetSize()), // size
7270
/*mip_count=*/1,
7371
"SceneContents", // label

impeller/entity/contents/tiled_texture_contents_unittests.cc

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ TEST_P(EntityTest, TiledTextureContentsRendersWithCorrectPipeline) {
3232

3333
auto content_context = GetContentContext();
3434
auto buffer = content_context->GetContext()->CreateCommandBuffer();
35-
auto render_target = RenderTarget::CreateOffscreenMSAA(
36-
*content_context->GetContext(),
37-
*GetContentContext()->GetRenderTargetCache(), {100, 100},
38-
/*mip_count=*/1);
35+
auto render_target =
36+
GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
37+
*content_context->GetContext(), {100, 100},
38+
/*mip_count=*/1);
3939
auto render_pass = buffer->CreateRenderPass(render_target);
4040
auto recording_pass = std::make_shared<RecordingRenderPass>(
4141
render_pass, GetContext(), render_target);
@@ -74,10 +74,10 @@ TEST_P(EntityTest, TiledTextureContentsRendersWithCorrectPipelineExternalOES) {
7474

7575
auto content_context = GetContentContext();
7676
auto buffer = content_context->GetContext()->CreateCommandBuffer();
77-
auto render_target = RenderTarget::CreateOffscreenMSAA(
78-
*content_context->GetContext(),
79-
*GetContentContext()->GetRenderTargetCache(), {100, 100},
80-
/*mip_count=*/1);
77+
auto render_target =
78+
GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
79+
*content_context->GetContext(), {100, 100},
80+
/*mip_count=*/1);
8181
auto render_pass = buffer->CreateRenderPass(render_target);
8282

8383
ASSERT_TRUE(contents.Render(*GetContentContext(), {}, *render_pass));

impeller/entity/contents/vertices_contents_unittests.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ TEST_P(EntityTest, RendersDstPerColorWithAlpha) {
6060

6161
auto content_context = GetContentContext();
6262
auto buffer = content_context->GetContext()->CreateCommandBuffer();
63-
auto render_target = RenderTarget::CreateOffscreenMSAA(
64-
*content_context->GetContext(),
65-
*GetContentContext()->GetRenderTargetCache(), {100, 100},
66-
/*mip_count=*/1);
63+
auto render_target =
64+
GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
65+
*content_context->GetContext(), {100, 100},
66+
/*mip_count=*/1);
6767
auto render_pass = buffer->CreateRenderPass(render_target);
6868
auto recording_pass = std::make_shared<RecordingRenderPass>(
6969
render_pass, GetContext(), render_target);

impeller/entity/entity_pass.cc

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -292,9 +292,8 @@ static EntityPassTarget CreateRenderTarget(ContentContext& renderer,
292292

293293
RenderTarget target;
294294
if (context->GetCapabilities()->SupportsOffscreenMSAA()) {
295-
target = RenderTarget::CreateOffscreenMSAA(
295+
target = renderer.GetRenderTargetCache()->CreateOffscreenMSAA(
296296
/*context=*/*context,
297-
/*allocator=*/*renderer.GetRenderTargetCache(),
298297
/*size=*/size,
299298
/*mip_count=*/mip_count,
300299
/*label=*/"EntityPass",
@@ -308,10 +307,9 @@ static EntityPassTarget CreateRenderTarget(ContentContext& renderer,
308307
/*stencil_attachment_config=*/
309308
kDefaultStencilConfig);
310309
} else {
311-
target = RenderTarget::CreateOffscreen(
312-
*context, // context
313-
*renderer.GetRenderTargetCache(), // allocator
314-
size, // size
310+
target = renderer.GetRenderTargetCache()->CreateOffscreen(
311+
*context, // context
312+
size, // size
315313
/*mip_count=*/mip_count,
316314
"EntityPass", // label
317315
RenderTarget::AttachmentConfig{
@@ -485,7 +483,7 @@ bool EntityPass::Render(ContentContext& renderer,
485483
// provided by the caller.
486484
else {
487485
root_render_target.SetupDepthStencilAttachments(
488-
*renderer.GetContext(), *renderer.GetRenderTargetCache(),
486+
*renderer.GetContext(), *renderer.GetContext()->GetResourceAllocator(),
489487
color0.texture->GetSize(),
490488
renderer.GetContext()->GetCapabilities()->SupportsOffscreenMSAA(),
491489
"ImpellerOnscreen", kDefaultStencilConfig);

impeller/entity/entity_pass_target_unittests.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ TEST_P(EntityPassTargetTest, SwapWithMSAATexture) {
2424
}
2525
auto content_context = GetContentContext();
2626
auto buffer = content_context->GetContext()->CreateCommandBuffer();
27-
auto render_target = RenderTarget::CreateOffscreenMSAA(
28-
*content_context->GetContext(),
29-
*GetContentContext()->GetRenderTargetCache(), {100, 100},
30-
/*mip_count=*/1);
27+
auto render_target =
28+
GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
29+
*content_context->GetContext(), {100, 100},
30+
/*mip_count=*/1);
3131

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

impeller/entity/entity_unittests.cc

Lines changed: 16 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "impeller/entity/geometry/geometry.h"
3939
#include "impeller/entity/geometry/point_field_geometry.h"
4040
#include "impeller/entity/geometry/stroke_path_geometry.h"
41+
#include "impeller/entity/render_target_cache.h"
4142
#include "impeller/geometry/color.h"
4243
#include "impeller/geometry/geometry_asserts.h"
4344
#include "impeller/geometry/path_builder.h"
@@ -2248,10 +2249,10 @@ TEST_P(EntityTest, RuntimeEffectCanSuccessfullyRender) {
22482249

22492250
// Create a render target with a depth-stencil, similar to how EntityPass
22502251
// does.
2251-
RenderTarget target = RenderTarget::CreateOffscreenMSAA(
2252-
*GetContext(), *GetContentContext()->GetRenderTargetCache(),
2253-
{GetWindowSize().width, GetWindowSize().height}, 1,
2254-
"RuntimeEffect Texture");
2252+
RenderTarget target =
2253+
GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
2254+
*GetContext(), {GetWindowSize().width, GetWindowSize().height}, 1,
2255+
"RuntimeEffect Texture");
22552256
testing::MockRenderPass pass(GetContext(), target);
22562257

22572258
ASSERT_TRUE(contents->Render(*GetContentContext(), entity, pass));
@@ -2590,33 +2591,6 @@ TEST_P(EntityTest, TextContentsCeilsGlyphScaleToDecimal) {
25902591
ASSERT_EQ(TextFrame::RoundScaledFontSize(0.0f, 12), 0.0f);
25912592
}
25922593

2593-
class TestRenderTargetAllocator : public RenderTargetAllocator {
2594-
public:
2595-
explicit TestRenderTargetAllocator(std::shared_ptr<Allocator> allocator)
2596-
: RenderTargetAllocator(std::move(allocator)) {}
2597-
2598-
~TestRenderTargetAllocator() = default;
2599-
2600-
std::shared_ptr<Texture> CreateTexture(
2601-
const TextureDescriptor& desc) override {
2602-
allocated_.push_back(desc);
2603-
return RenderTargetAllocator::CreateTexture(desc);
2604-
}
2605-
2606-
void Start() override { RenderTargetAllocator::Start(); }
2607-
2608-
void End() override { RenderTargetAllocator::End(); }
2609-
2610-
std::vector<TextureDescriptor> GetAllocatedTextureDescriptors() const {
2611-
return allocated_;
2612-
}
2613-
2614-
void ResetDescriptors() { allocated_.clear(); }
2615-
2616-
private:
2617-
std::vector<TextureDescriptor> allocated_;
2618-
};
2619-
26202594
TEST_P(EntityTest, AdvancedBlendCoverageHintIsNotResetByEntityPass) {
26212595
if (GetContext()->GetCapabilities()->SupportsFramebufferFetch()) {
26222596
GTEST_SKIP() << "Backends that support framebuffer fetch dont use coverage "
@@ -2636,31 +2610,29 @@ TEST_P(EntityTest, AdvancedBlendCoverageHintIsNotResetByEntityPass) {
26362610
EXPECT_TRUE(coverage.has_value());
26372611

26382612
auto pass = std::make_unique<EntityPass>();
2639-
auto test_allocator = std::make_shared<TestRenderTargetAllocator>(
2640-
GetContext()->GetResourceAllocator());
2613+
std::shared_ptr<RenderTargetCache> render_target_allocator =
2614+
std::make_shared<RenderTargetCache>(GetContext()->GetResourceAllocator());
26412615
auto stencil_config = RenderTarget::AttachmentConfig{
26422616
.storage_mode = StorageMode::kDevicePrivate,
26432617
.load_action = LoadAction::kClear,
26442618
.store_action = StoreAction::kDontCare,
26452619
.clear_color = Color::BlackTransparent()};
2646-
auto rt = RenderTarget::CreateOffscreen(
2647-
*GetContext(), *test_allocator, ISize::MakeWH(1000, 1000),
2620+
auto rt = render_target_allocator->CreateOffscreen(
2621+
*GetContext(), ISize::MakeWH(1000, 1000),
26482622
/*mip_count=*/1, "Offscreen", RenderTarget::kDefaultColorAttachmentConfig,
26492623
stencil_config);
26502624
auto content_context = ContentContext(
2651-
GetContext(), TypographerContextSkia::Make(), test_allocator);
2625+
GetContext(), TypographerContextSkia::Make(), render_target_allocator);
26522626
pass->AddEntity(std::move(entity));
2653-
test_allocator->ResetDescriptors();
26542627

26552628
EXPECT_TRUE(pass->Render(content_context, rt));
26562629

2657-
std::vector<TextureDescriptor> descriptors =
2658-
test_allocator->GetAllocatedTextureDescriptors();
2659-
2660-
auto contains_size = [&descriptors](ISize size) -> bool {
2661-
return std::find_if(descriptors.begin(), descriptors.end(),
2662-
[&size](auto desc) { return desc.size == size; }) !=
2663-
descriptors.end();
2630+
auto contains_size = [&render_target_allocator](ISize size) -> bool {
2631+
return std::find_if(render_target_allocator->GetRenderTargetDataBegin(),
2632+
render_target_allocator->GetRenderTargetDataEnd(),
2633+
[&size](const auto& data) {
2634+
return data.config.size == size;
2635+
}) != render_target_allocator->GetRenderTargetDataEnd();
26642636
};
26652637

26662638
EXPECT_TRUE(contains_size(ISize(1000, 1000)))

0 commit comments

Comments
 (0)