[Impeller] tear down swapchain when backgrounding. (#165259)

When we return to the foreground the swapchain is reconstructed anyway.
Eagerly tearing the old one down releases memory faster. Highlighted by
a regression in a customer: money benchmark.
This commit is contained in:
Jonah Williams
2025-03-18 12:26:11 -07:00
committed by GitHub
parent 6912a06f35
commit 05c868e744
6 changed files with 60 additions and 1 deletions

View File

@@ -206,6 +206,7 @@
../../../flutter/impeller/renderer/backend/vulkan/render_pass_cache_unittests.cc
../../../flutter/impeller/renderer/backend/vulkan/render_pass_vk_unittests.cc
../../../flutter/impeller/renderer/backend/vulkan/resource_manager_vk_unittests.cc
../../../flutter/impeller/renderer/backend/vulkan/surface_context_vk_unittests.cc
../../../flutter/impeller/renderer/backend/vulkan/swapchain/README.md
../../../flutter/impeller/renderer/backend/vulkan/swapchain/khr/README.md
../../../flutter/impeller/renderer/backend/vulkan/test

View File

@@ -22,6 +22,7 @@ impeller_component("vulkan_unittests") {
"render_pass_cache_unittests.cc",
"render_pass_vk_unittests.cc",
"resource_manager_vk_unittests.cc",
"surface_context_vk_unittests.cc",
"test/gpu_tracer_unittests.cc",
"test/mock_vulkan.cc",
"test/mock_vulkan.h",

View File

@@ -72,6 +72,13 @@ bool SurfaceContextVK::SetWindowSurface(vk::UniqueSurfaceKHR surface,
return SetSwapchain(SwapchainVK::Create(parent_, std::move(surface), size));
}
void SurfaceContextVK::TeardownSwapchain() {
// When background the application, tear down the swapchain to release memory
// from the images. When returning to the foreground, SetWindowSurface will be
// called which will re-create the swapchain.
swapchain_.reset();
}
bool SurfaceContextVK::SetSwapchain(std::shared_ptr<SwapchainVK> swapchain) {
if (!swapchain || !swapchain->IsValid()) {
VALIDATION_LOG << "Invalid swapchain.";

View File

@@ -96,6 +96,9 @@ class SurfaceContextVK : public Context,
/// recreated on the next frame.
void UpdateSurfaceSize(const ISize& size) const;
/// @brief Can be called when the surface is destroyed to reduce memory usage.
void TeardownSwapchain();
// |Context|
void InitializeCommonlyUsedShadersIfNeeded() const override;

View File

@@ -0,0 +1,47 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <sys/types.h>
#include <memory>
#include <utility>
#include "gtest/gtest.h"
#include "impeller/renderer/backend/vulkan/surface_context_vk.h"
#include "impeller/renderer/backend/vulkan/test/mock_vulkan.h"
#include "impeller/renderer/surface.h"
namespace impeller {
namespace testing {
namespace {
vk::UniqueSurfaceKHR CreateSurface(const ContextVK& context) {
#if FML_OS_DARWIN
impeller::vk::MetalSurfaceCreateInfoEXT createInfo = {};
auto [result, surface] =
context.GetInstance().createMetalSurfaceEXTUnique(createInfo);
FML_DCHECK(result == vk::Result::eSuccess);
return std::move(surface);
#else
return {};
#endif // FML_OS_DARWIN
}
} // namespace
TEST(SurfaceContextVK, TearsDownSwapchain) {
SetSwapchainImageSize({100, 100});
std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
vk::UniqueSurfaceKHR surface = CreateSurface(*context);
SurfaceContextVK surface_context(context);
EXPECT_TRUE(surface_context.SetWindowSurface(std::move(surface), {100, 100}));
EXPECT_NE(surface_context.AcquireNextSurface(), nullptr);
surface_context.TeardownSwapchain();
EXPECT_EQ(surface_context.AcquireNextSurface(), nullptr);
}
} // namespace testing
} // namespace impeller

View File

@@ -37,7 +37,7 @@ bool AndroidSurfaceVKImpeller::IsValid() const {
}
void AndroidSurfaceVKImpeller::TeardownOnScreenContext() {
// Nothing to do.
surface_context_vk_->TeardownSwapchain();
}
std::unique_ptr<Surface> AndroidSurfaceVKImpeller::CreateGPUSurface(