Description
WrappedTextureSourceVK in shell/gpu/gpu_surface_vulkan_impeller.cc leaks a VkImageView every frame when using the embedder delegate code path.
Steps to reproduce
- Create a custom embedder using
FlutterVulkanRendererConfig (the Vulkan delegate path)
- Run any Flutter app
- Each frame,
AcquireFrame calls createImageView() and stores the result as a raw vk::ImageView
- The destructor
~WrappedTextureSourceVK() {} is empty — the VkImageView is never destroyed
This leaks ~60 VkImageView handles per second. On a long-running app this will eventually exhaust driver resources.
Analysis
The fix is straightforward: use vk::UniqueImageView instead of raw vk::ImageView for RAII ownership. The resource lifetime is safe because Impeller's TrackedObjectsVK holds a shared_ptr<TextureSourceVK> until the GPU fence signals completion, preventing premature destruction.
This only affects the embedder delegate path (delegate_ != nullptr). Android passes nullptr as the delegate and uses AcquireNextSurface() instead, so Android is not affected.
Environment
- Found on Linux/Wayland with a custom Vulkan embedder
- NVIDIA GeForce RTX 5070 Ti, driver 570.x
- Flutter engine at commit f916dd6
Labels
e: impeller
platform-linux
P2
Description
WrappedTextureSourceVKinshell/gpu/gpu_surface_vulkan_impeller.ccleaks aVkImageViewevery frame when using the embedder delegate code path.Steps to reproduce
FlutterVulkanRendererConfig(the Vulkan delegate path)AcquireFramecallscreateImageView()and stores the result as a rawvk::ImageView~WrappedTextureSourceVK() {}is empty — theVkImageViewis never destroyedThis leaks ~60
VkImageViewhandles per second. On a long-running app this will eventually exhaust driver resources.Analysis
The fix is straightforward: use
vk::UniqueImageViewinstead of rawvk::ImageViewfor RAII ownership. The resource lifetime is safe because Impeller'sTrackedObjectsVKholds ashared_ptr<TextureSourceVK>until the GPU fence signals completion, preventing premature destruction.This only affects the embedder delegate path (
delegate_ != nullptr). Android passesnullptras the delegate and usesAcquireNextSurface()instead, so Android is not affected.Environment
Labels
e: impellerplatform-linuxP2