From f6a8993570ec669cacaab551be4e2431424d6844 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Tue, 29 Apr 2025 09:39:45 +0200 Subject: [PATCH] Fix #137382: Vulkan: Memory leak when rendering Each time when rendering an image a new context is created. When the context is destroyed it can still contain a render graph, which ownership isn't transferred back to the device. Resulting in an increase of several MB per render. The render graph is cleanly destroyed during quiting as there is a master list of created render graphs. Fixed by moving the ownership of the render graph back to the device when a context is unregistered. Pull Request: https://projects.blender.org/blender/blender/pulls/138095 --- source/blender/gpu/vulkan/vk_context.hh | 3 +++ source/blender/gpu/vulkan/vk_device.cc | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/source/blender/gpu/vulkan/vk_context.hh b/source/blender/gpu/vulkan/vk_context.hh index 2cdf733a3cc..2a16c314ca7 100644 --- a/source/blender/gpu/vulkan/vk_context.hh +++ b/source/blender/gpu/vulkan/vk_context.hh @@ -27,6 +27,7 @@ class VKBatch; class VKStateManager; class VKShader; class VKThreadData; +class VKDevice; enum RenderGraphFlushFlags { NONE = 0, @@ -37,6 +38,8 @@ enum RenderGraphFlushFlags { ENUM_OPERATORS(RenderGraphFlushFlags, RenderGraphFlushFlags::WAIT_FOR_COMPLETION); class VKContext : public Context, NonCopyable { + friend class VKDevice; + private: VkExtent2D vk_extent_ = {}; VkSurfaceFormatKHR swap_chain_format_ = {}; diff --git a/source/blender/gpu/vulkan/vk_device.cc b/source/blender/gpu/vulkan/vk_device.cc index f9c431325d3..154a2e28679 100644 --- a/source/blender/gpu/vulkan/vk_device.cc +++ b/source/blender/gpu/vulkan/vk_device.cc @@ -464,6 +464,14 @@ void VKDevice::context_register(VKContext &context) void VKDevice::context_unregister(VKContext &context) { + if (context.render_graph_.has_value()) { + render_graph::VKRenderGraph &render_graph = context.render_graph(); + context.render_graph_.reset(); + BLI_assert_msg(render_graph.is_empty(), + "Unregistering a context that still has an unsubmitted render graph."); + render_graph.reset(); + BLI_thread_queue_push(unused_render_graphs_, &render_graph); + } orphaned_data.move_data(context.discard_pool, timeline_value_ + 1); contexts_.remove(contexts_.first_index_of(std::reference_wrapper(context))); }