Summary
Hi!
We found that on Linux Vulkan, UE 5.8.2 leaks RAM on every parallel render pass.
It was confirmed on 2 separate machines with different GPUs. Occurs in both 5.8.0 and 5.8.2.
RHIBeginParallelRenderPass() does new FVulkanDynamicRenderingInfo(). RHIEndParallelRenderPass() deletes CurrentParallelRenderPassInfo and leaves DynamicRenderingInfo behind. FVulkanParallelRenderPassInfo has no destructor. File: Engine/Source/Runtime/VulkanRHI/Private/VulkanContext.cpp.
We saw it on two Linux machines running a packaged offscreen project, with several SceneCaptures and hardware ray-traced LiDAR:
machine1: process grew to ~114 GB and the kernel OOM-killed it.machine2: anonymous RSS grew ~1.5 GB/h. Insights + addr2line on matching debug symbols pointed at FVulkanCommandListContext::RHIBeginParallelRenderPass - operator new.
Workaround:
we tested r.Vulkan.AllowDynamicRendering=0, which reduced memory leak from about 1.5GB/h to 0.27 GB/h
What Type of Bug are you experiencing?
Simulation
Steps to Reproduce
- Package a Linux Vulkan build of a project that uses parallel render passes (SceneCapture / hardware ray tracing is enough).
- Run it offscreen for 20+ minutes (-RenderOffscreen).
- Watch process RSS / anonymous memory.
Optional: Insights memory trace, then addr2line on RHIBeginParallelRenderPass.
Optional: r.Vulkan.AllowDynamicRendering=0 at startup and repeat.
Expected Result
No memory leak
Observed Result
RSS climbs about 1.5 GiB/h (on 2 separate machines). Same binary on sw-perc-1 grew to ~114 GB and was OOM-killed. Trace shows RHIBeginParallelRenderPass → operator new. r.Vulkan.AllowDynamicRendering=0 drops growth to ~0.27 GiB/h. Still present in 5.8.0 and 5.8.2 source.
Affects Versions
5.8
Platform(s)
Linux
Additional Notes
Proposed fix:
From: Filip Kubicz <filip@kubicz.engineer>
Date: Fri, 11 Sep 2026 12:37:00 +0200
Subject: [PATCH] VulkanRHI: free FVulkanDynamicRenderingInfo on parallel pass end
RHIBeginParallelRenderPass heap-allocates DynamicRenderingInfo.
RHIEndParallelRenderPass only deletes CurrentParallelRenderPassInfo,
so the inner object leaks every pass.
---
Engine/Source/Runtime/VulkanRHI/Private/VulkanContext.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/Engine/Source/Runtime/VulkanRHI/Private/VulkanContext.h b/Engine/Source/Runtime/VulkanRHI/Private/VulkanContext.h
index 0000000..1111111 100644
--- a/Engine/Source/Runtime/VulkanRHI/Private/VulkanContext.h
+++ b/Engine/Source/Runtime/VulkanRHI/Private/VulkanContext.h
@@ -49,6 +49,11 @@
struct FVulkanParallelRenderPassInfo
{
VkRenderPass RenderPassHandle = VK_NULL_HANDLE;
FVulkanDynamicRenderingInfo* DynamicRenderingInfo = nullptr;
TArray<FVulkanPayload*> SecondaryPayloads;
std::atomic<int32> NumParallelContexts = 0;
+
+ ~FVulkanParallelRenderPassInfo()
+ {
+ delete DynamicRenderingInfo;
+ }
};