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

Commit 792bfc7

Browse files
[Impeller] Create a new render target with the specified attachment configs when reusing cached render target textures (#51208)
If the RenderTargetCache::Create methods reuse a cached RenderTarget as is, then the returned RenderTarget may contain AttachmentConfig parameters that do not match the ones passed to the create method. This PR instead creates a new RenderTarget based on the existing textures from the cached RenderTarget.
1 parent 20037e3 commit 792bfc7

File tree

5 files changed

+166
-90
lines changed

5 files changed

+166
-90
lines changed

impeller/entity/render_target_cache.cc

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,11 @@ RenderTarget RenderTargetCache::CreateOffscreen(
3333
int mip_count,
3434
const std::string& label,
3535
RenderTarget::AttachmentConfig color_attachment_config,
36-
std::optional<RenderTarget::AttachmentConfig> stencil_attachment_config) {
36+
std::optional<RenderTarget::AttachmentConfig> stencil_attachment_config,
37+
const std::shared_ptr<Texture>& existing_color_texture,
38+
const std::shared_ptr<Texture>& existing_depth_stencil_texture) {
39+
FML_DCHECK(existing_color_texture == nullptr &&
40+
existing_depth_stencil_texture == nullptr);
3741
auto config = RenderTargetConfig{
3842
.size = size,
3943
.mip_count = static_cast<size_t>(mip_count),
@@ -44,7 +48,14 @@ RenderTarget RenderTargetCache::CreateOffscreen(
4448
const auto other_config = render_target_data.config;
4549
if (!render_target_data.used_this_frame && other_config == config) {
4650
render_target_data.used_this_frame = true;
47-
return render_target_data.render_target;
51+
auto color0 = render_target_data.render_target.GetColorAttachments()
52+
.find(0u)
53+
->second;
54+
auto depth = render_target_data.render_target.GetDepthAttachment();
55+
std::shared_ptr<Texture> depth_tex = depth ? depth->texture : nullptr;
56+
return RenderTargetAllocator::CreateOffscreen(
57+
context, size, mip_count, label, color_attachment_config,
58+
stencil_attachment_config, color0.texture, depth_tex);
4859
}
4960
}
5061
RenderTarget created_target = RenderTargetAllocator::CreateOffscreen(
@@ -66,7 +77,13 @@ RenderTarget RenderTargetCache::CreateOffscreenMSAA(
6677
int mip_count,
6778
const std::string& label,
6879
RenderTarget::AttachmentConfigMSAA color_attachment_config,
69-
std::optional<RenderTarget::AttachmentConfig> stencil_attachment_config) {
80+
std::optional<RenderTarget::AttachmentConfig> stencil_attachment_config,
81+
const std::shared_ptr<Texture>& existing_color_msaa_texture,
82+
const std::shared_ptr<Texture>& existing_color_resolve_texture,
83+
const std::shared_ptr<Texture>& existing_depth_stencil_texture) {
84+
FML_DCHECK(existing_color_msaa_texture == nullptr &&
85+
existing_color_resolve_texture == nullptr &&
86+
existing_depth_stencil_texture == nullptr);
7087
auto config = RenderTargetConfig{
7188
.size = size,
7289
.mip_count = static_cast<size_t>(mip_count),
@@ -77,7 +94,15 @@ RenderTarget RenderTargetCache::CreateOffscreenMSAA(
7794
const auto other_config = render_target_data.config;
7895
if (!render_target_data.used_this_frame && other_config == config) {
7996
render_target_data.used_this_frame = true;
80-
return render_target_data.render_target;
97+
auto color0 = render_target_data.render_target.GetColorAttachments()
98+
.find(0u)
99+
->second;
100+
auto depth = render_target_data.render_target.GetDepthAttachment();
101+
std::shared_ptr<Texture> depth_tex = depth ? depth->texture : nullptr;
102+
return RenderTargetAllocator::CreateOffscreenMSAA(
103+
context, size, mip_count, label, color_attachment_config,
104+
stencil_attachment_config, color0.texture, color0.resolve_texture,
105+
depth_tex);
81106
}
82107
}
83108
RenderTarget created_target = RenderTargetAllocator::CreateOffscreenMSAA(

impeller/entity/render_target_cache.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@ class RenderTargetCache : public RenderTargetAllocator {
3333
RenderTarget::AttachmentConfig color_attachment_config =
3434
RenderTarget::kDefaultColorAttachmentConfig,
3535
std::optional<RenderTarget::AttachmentConfig> stencil_attachment_config =
36-
RenderTarget::kDefaultStencilAttachmentConfig) override;
36+
RenderTarget::kDefaultStencilAttachmentConfig,
37+
const std::shared_ptr<Texture>& existing_color_texture = nullptr,
38+
const std::shared_ptr<Texture>& existing_depth_stencil_texture =
39+
nullptr) override;
3740

3841
RenderTarget CreateOffscreenMSAA(
3942
const Context& context,
@@ -43,7 +46,11 @@ class RenderTargetCache : public RenderTargetAllocator {
4346
RenderTarget::AttachmentConfigMSAA color_attachment_config =
4447
RenderTarget::kDefaultColorAttachmentConfigMSAA,
4548
std::optional<RenderTarget::AttachmentConfig> stencil_attachment_config =
46-
RenderTarget::kDefaultStencilAttachmentConfig) override;
49+
RenderTarget::kDefaultStencilAttachmentConfig,
50+
const std::shared_ptr<Texture>& existing_color_msaa_texture = nullptr,
51+
const std::shared_ptr<Texture>& existing_color_resolve_texture = nullptr,
52+
const std::shared_ptr<Texture>& existing_depth_stencil_texture =
53+
nullptr) override;
4754

4855
// visible for testing.
4956
size_t CachedTextureCount() const;

impeller/entity/render_target_cache_unittests.cc

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,5 +87,30 @@ TEST_P(RenderTargetCacheTest, DoesNotPersistFailedAllocations) {
8787
EXPECT_EQ(render_target_cache.CachedTextureCount(), 0u);
8888
}
8989

90+
TEST_P(RenderTargetCacheTest, CachedTextureGetsNewAttachmentConfig) {
91+
auto render_target_cache =
92+
RenderTargetCache(GetContext()->GetResourceAllocator());
93+
94+
render_target_cache.Start();
95+
RenderTarget::AttachmentConfig color_attachment_config =
96+
RenderTarget::kDefaultColorAttachmentConfig;
97+
RenderTarget target1 = render_target_cache.CreateOffscreen(
98+
*GetContext(), {100, 100}, 1, "Offscreen1", color_attachment_config);
99+
render_target_cache.End();
100+
101+
render_target_cache.Start();
102+
color_attachment_config.clear_color = Color::Red();
103+
RenderTarget target2 = render_target_cache.CreateOffscreen(
104+
*GetContext(), {100, 100}, 1, "Offscreen2", color_attachment_config);
105+
render_target_cache.End();
106+
107+
auto color1 = target1.GetColorAttachments().find(0)->second;
108+
auto color2 = target2.GetColorAttachments().find(0)->second;
109+
// The second color attachment should reuse the first attachment's texture
110+
// but with attributes from the second AttachmentConfig.
111+
EXPECT_EQ(color2.texture, color1.texture);
112+
EXPECT_EQ(color2.clear_color, Color::Red());
113+
}
114+
90115
} // namespace testing
91116
} // namespace impeller

impeller/renderer/render_target.cc

Lines changed: 94 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -261,37 +261,46 @@ RenderTarget RenderTargetAllocator::CreateOffscreen(
261261
int mip_count,
262262
const std::string& label,
263263
RenderTarget::AttachmentConfig color_attachment_config,
264-
std::optional<RenderTarget::AttachmentConfig> stencil_attachment_config) {
264+
std::optional<RenderTarget::AttachmentConfig> stencil_attachment_config,
265+
const std::shared_ptr<Texture>& existing_color_texture,
266+
const std::shared_ptr<Texture>& existing_depth_stencil_texture) {
265267
if (size.IsEmpty()) {
266268
return {};
267269
}
268270

269271
RenderTarget target;
270-
PixelFormat pixel_format = context.GetCapabilities()->GetDefaultColorFormat();
271-
TextureDescriptor color_tex0;
272-
color_tex0.storage_mode = color_attachment_config.storage_mode;
273-
color_tex0.format = pixel_format;
274-
color_tex0.size = size;
275-
color_tex0.mip_count = mip_count;
276-
color_tex0.usage = static_cast<uint64_t>(TextureUsage::kRenderTarget) |
277-
static_cast<uint64_t>(TextureUsage::kShaderRead);
272+
273+
std::shared_ptr<Texture> color0_tex;
274+
if (existing_color_texture) {
275+
color0_tex = existing_color_texture;
276+
} else {
277+
PixelFormat pixel_format =
278+
context.GetCapabilities()->GetDefaultColorFormat();
279+
TextureDescriptor color0_tex_desc;
280+
color0_tex_desc.storage_mode = color_attachment_config.storage_mode;
281+
color0_tex_desc.format = pixel_format;
282+
color0_tex_desc.size = size;
283+
color0_tex_desc.mip_count = mip_count;
284+
color0_tex_desc.usage = static_cast<uint64_t>(TextureUsage::kRenderTarget) |
285+
static_cast<uint64_t>(TextureUsage::kShaderRead);
286+
color0_tex = allocator_->CreateTexture(color0_tex_desc);
287+
if (!color0_tex) {
288+
return {};
289+
}
290+
}
291+
color0_tex->SetLabel(SPrintF("%s Color Texture", label.c_str()));
278292

279293
ColorAttachment color0;
280294
color0.clear_color = color_attachment_config.clear_color;
281295
color0.load_action = color_attachment_config.load_action;
282296
color0.store_action = color_attachment_config.store_action;
283-
color0.texture = allocator_->CreateTexture(color_tex0);
284-
285-
if (!color0.texture) {
286-
return {};
287-
}
288-
color0.texture->SetLabel(SPrintF("%s Color Texture", label.c_str()));
297+
color0.texture = color0_tex;
289298
target.SetColorAttachment(color0, 0u);
290299

291300
if (stencil_attachment_config.has_value()) {
292-
target.SetupDepthStencilAttachments(context, *allocator_, size, false,
293-
label,
294-
stencil_attachment_config.value());
301+
target.SetupDepthStencilAttachments(
302+
context, *allocator_, size, false, label,
303+
stencil_attachment_config.value(), existing_depth_stencil_texture);
295304
} else {
296305
target.SetStencilAttachment(std::nullopt);
297306
target.SetDepthAttachment(std::nullopt);
@@ -306,7 +315,10 @@ RenderTarget RenderTargetAllocator::CreateOffscreenMSAA(
306315
int mip_count,
307316
const std::string& label,
308317
RenderTarget::AttachmentConfigMSAA color_attachment_config,
309-
std::optional<RenderTarget::AttachmentConfig> stencil_attachment_config) {
318+
std::optional<RenderTarget::AttachmentConfig> stencil_attachment_config,
319+
const std::shared_ptr<Texture>& existing_color_msaa_texture,
320+
const std::shared_ptr<Texture>& existing_color_resolve_texture,
321+
const std::shared_ptr<Texture>& existing_depth_stencil_texture) {
310322
if (size.IsEmpty()) {
311323
return {};
312324
}
@@ -315,45 +327,50 @@ RenderTarget RenderTargetAllocator::CreateOffscreenMSAA(
315327
PixelFormat pixel_format = context.GetCapabilities()->GetDefaultColorFormat();
316328

317329
// Create MSAA color texture.
318-
319-
TextureDescriptor color0_tex_desc;
320-
color0_tex_desc.storage_mode = color_attachment_config.storage_mode;
321-
color0_tex_desc.type = TextureType::kTexture2DMultisample;
322-
color0_tex_desc.sample_count = SampleCount::kCount4;
323-
color0_tex_desc.format = pixel_format;
324-
color0_tex_desc.size = size;
325-
color0_tex_desc.usage = static_cast<uint64_t>(TextureUsage::kRenderTarget);
326-
327-
if (context.GetCapabilities()->SupportsImplicitResolvingMSAA()) {
328-
// See below ("SupportsImplicitResolvingMSAA") for more details.
329-
color0_tex_desc.storage_mode = StorageMode::kDevicePrivate;
330-
}
331-
332-
auto color0_msaa_tex = allocator_->CreateTexture(color0_tex_desc);
333-
if (!color0_msaa_tex) {
334-
VALIDATION_LOG << "Could not create multisample color texture.";
335-
return {};
330+
std::shared_ptr<Texture> color0_msaa_tex;
331+
if (existing_color_msaa_texture) {
332+
color0_msaa_tex = existing_color_msaa_texture;
333+
} else {
334+
TextureDescriptor color0_tex_desc;
335+
color0_tex_desc.storage_mode = color_attachment_config.storage_mode;
336+
color0_tex_desc.type = TextureType::kTexture2DMultisample;
337+
color0_tex_desc.sample_count = SampleCount::kCount4;
338+
color0_tex_desc.format = pixel_format;
339+
color0_tex_desc.size = size;
340+
color0_tex_desc.usage = static_cast<uint64_t>(TextureUsage::kRenderTarget);
341+
if (context.GetCapabilities()->SupportsImplicitResolvingMSAA()) {
342+
// See below ("SupportsImplicitResolvingMSAA") for more details.
343+
color0_tex_desc.storage_mode = StorageMode::kDevicePrivate;
344+
}
345+
color0_msaa_tex = allocator_->CreateTexture(color0_tex_desc);
346+
if (!color0_msaa_tex) {
347+
VALIDATION_LOG << "Could not create multisample color texture.";
348+
return {};
349+
}
336350
}
337351
color0_msaa_tex->SetLabel(
338352
SPrintF("%s Color Texture (Multisample)", label.c_str()));
339353

340354
// Create color resolve texture.
341-
342-
TextureDescriptor color0_resolve_tex_desc;
343-
color0_resolve_tex_desc.storage_mode =
344-
color_attachment_config.resolve_storage_mode;
345-
color0_resolve_tex_desc.format = pixel_format;
346-
color0_resolve_tex_desc.size = size;
347-
color0_resolve_tex_desc.compression_type = CompressionType::kLossy;
348-
color0_resolve_tex_desc.usage =
349-
static_cast<uint64_t>(TextureUsage::kRenderTarget) |
350-
static_cast<uint64_t>(TextureUsage::kShaderRead);
351-
color0_resolve_tex_desc.mip_count = mip_count;
352-
353-
auto color0_resolve_tex = allocator_->CreateTexture(color0_resolve_tex_desc);
354-
if (!color0_resolve_tex) {
355-
VALIDATION_LOG << "Could not create color texture.";
356-
return {};
355+
std::shared_ptr<Texture> color0_resolve_tex;
356+
if (existing_color_resolve_texture) {
357+
color0_resolve_tex = existing_color_resolve_texture;
358+
} else {
359+
TextureDescriptor color0_resolve_tex_desc;
360+
color0_resolve_tex_desc.storage_mode =
361+
color_attachment_config.resolve_storage_mode;
362+
color0_resolve_tex_desc.format = pixel_format;
363+
color0_resolve_tex_desc.size = size;
364+
color0_resolve_tex_desc.compression_type = CompressionType::kLossy;
365+
color0_resolve_tex_desc.usage =
366+
static_cast<uint64_t>(TextureUsage::kRenderTarget) |
367+
static_cast<uint64_t>(TextureUsage::kShaderRead);
368+
color0_resolve_tex_desc.mip_count = mip_count;
369+
color0_resolve_tex = allocator_->CreateTexture(color0_resolve_tex_desc);
370+
if (!color0_resolve_tex) {
371+
VALIDATION_LOG << "Could not create color texture.";
372+
return {};
373+
}
357374
}
358375
color0_resolve_tex->SetLabel(SPrintF("%s Color Texture", label.c_str()));
359376

@@ -383,7 +400,8 @@ RenderTarget RenderTargetAllocator::CreateOffscreenMSAA(
383400

384401
if (stencil_attachment_config.has_value()) {
385402
target.SetupDepthStencilAttachments(context, *allocator_, size, true, label,
386-
stencil_attachment_config.value());
403+
stencil_attachment_config.value(),
404+
existing_depth_stencil_texture);
387405
} else {
388406
target.SetDepthAttachment(std::nullopt);
389407
target.SetStencilAttachment(std::nullopt);
@@ -398,24 +416,28 @@ void RenderTarget::SetupDepthStencilAttachments(
398416
ISize size,
399417
bool msaa,
400418
const std::string& label,
401-
RenderTarget::AttachmentConfig stencil_attachment_config) {
402-
TextureDescriptor depth_stencil_texture_desc;
403-
depth_stencil_texture_desc.storage_mode =
404-
stencil_attachment_config.storage_mode;
405-
if (msaa) {
406-
depth_stencil_texture_desc.type = TextureType::kTexture2DMultisample;
407-
depth_stencil_texture_desc.sample_count = SampleCount::kCount4;
408-
}
409-
depth_stencil_texture_desc.format =
410-
context.GetCapabilities()->GetDefaultDepthStencilFormat();
411-
depth_stencil_texture_desc.size = size;
412-
depth_stencil_texture_desc.usage =
413-
static_cast<TextureUsageMask>(TextureUsage::kRenderTarget);
414-
415-
auto depth_stencil_texture =
416-
allocator.CreateTexture(depth_stencil_texture_desc);
417-
if (!depth_stencil_texture) {
418-
return; // Error messages are handled by `Allocator::CreateTexture`.
419+
RenderTarget::AttachmentConfig stencil_attachment_config,
420+
const std::shared_ptr<Texture>& existing_depth_stencil_texture) {
421+
std::shared_ptr<Texture> depth_stencil_texture;
422+
if (existing_depth_stencil_texture) {
423+
depth_stencil_texture = existing_depth_stencil_texture;
424+
} else {
425+
TextureDescriptor depth_stencil_texture_desc;
426+
depth_stencil_texture_desc.storage_mode =
427+
stencil_attachment_config.storage_mode;
428+
if (msaa) {
429+
depth_stencil_texture_desc.type = TextureType::kTexture2DMultisample;
430+
depth_stencil_texture_desc.sample_count = SampleCount::kCount4;
431+
}
432+
depth_stencil_texture_desc.format =
433+
context.GetCapabilities()->GetDefaultDepthStencilFormat();
434+
depth_stencil_texture_desc.size = size;
435+
depth_stencil_texture_desc.usage =
436+
static_cast<TextureUsageMask>(TextureUsage::kRenderTarget);
437+
depth_stencil_texture = allocator.CreateTexture(depth_stencil_texture_desc);
438+
if (!depth_stencil_texture) {
439+
return; // Error messages are handled by `Allocator::CreateTexture`.
440+
}
419441
}
420442

421443
DepthAttachment depth0;

impeller/renderer/render_target.h

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ class RenderTarget final {
8484
bool msaa,
8585
const std::string& label = "Offscreen",
8686
RenderTarget::AttachmentConfig stencil_attachment_config =
87-
RenderTarget::kDefaultStencilAttachmentConfig);
87+
RenderTarget::kDefaultStencilAttachmentConfig,
88+
const std::shared_ptr<Texture>& depth_stencil_texture = nullptr);
8889

8990
SampleCount GetSampleCount() const;
9091

@@ -152,7 +153,9 @@ class RenderTargetAllocator {
152153
RenderTarget::AttachmentConfig color_attachment_config =
153154
RenderTarget::kDefaultColorAttachmentConfig,
154155
std::optional<RenderTarget::AttachmentConfig> stencil_attachment_config =
155-
RenderTarget::kDefaultStencilAttachmentConfig);
156+
RenderTarget::kDefaultStencilAttachmentConfig,
157+
const std::shared_ptr<Texture>& existing_color_texture = nullptr,
158+
const std::shared_ptr<Texture>& existing_depth_stencil_texture = nullptr);
156159

157160
virtual RenderTarget CreateOffscreenMSAA(
158161
const Context& context,
@@ -162,7 +165,10 @@ class RenderTargetAllocator {
162165
RenderTarget::AttachmentConfigMSAA color_attachment_config =
163166
RenderTarget::kDefaultColorAttachmentConfigMSAA,
164167
std::optional<RenderTarget::AttachmentConfig> stencil_attachment_config =
165-
RenderTarget::kDefaultStencilAttachmentConfig);
168+
RenderTarget::kDefaultStencilAttachmentConfig,
169+
const std::shared_ptr<Texture>& existing_color_msaa_texture = nullptr,
170+
const std::shared_ptr<Texture>& existing_color_resolve_texture = nullptr,
171+
const std::shared_ptr<Texture>& existing_depth_stencil_texture = nullptr);
166172

167173
/// @brief Mark the beginning of a frame workload.
168174
///
@@ -176,15 +182,6 @@ class RenderTargetAllocator {
176182
virtual void End();
177183

178184
private:
179-
void SetupDepthStencilAttachments(
180-
Allocator& allocator,
181-
const Context& context,
182-
ISize size,
183-
bool msaa,
184-
const std::string& label = "Offscreen",
185-
RenderTarget::AttachmentConfig stencil_attachment_config =
186-
RenderTarget::kDefaultStencilAttachmentConfig);
187-
188185
std::shared_ptr<Allocator> allocator_;
189186
};
190187

0 commit comments

Comments
 (0)