[UE 5.7] Severe Memory Leak (STAT_RTAccelerationStructureMemory) with SceneCaptureComponent2D (RT/Lumen Disabled)

Description:

We are experiencing a severe, unbounded memory leak (growing by GBs over a short time) associated with USceneCaptureComponent2D. The memory bloat is tracked under STAT_RTAccelerationStructureMemory.

Using D3D12.DumpRayTracingGeometries confirmed that the actual BLAS geometry is small (~125MB) and not leaking. The massive allocation is entirely orphaned Ray Tracing Scratch Buffers (RHIScratchBuffer) building up indefinitely. This occurs specifically when rendering a scene capture without RT or Lumen enabled.

Root Cause Analysis:

I traced the leak down to the View State lifecycle on the Render Thread.

When the Scene Capture renders, it calls FRayTracingScene::AddView(). However, FRayTracingScene::RemoveView() is *never* called when the Pawn (and its capture component) is destroyed. This leaves the orphaned view permanently registered in the main world’s FRayTracingScene, forcing the RHI to continually hold transient Scratch Buffers.

The reason RemoveView() is never called is due to a lifecycle flaw involving FSceneViewState::~FSceneViewState().

The destructor expects to clean itself up via Scene->RemoveViewState_RenderThread(this). However, Scene is nullptr in this case.

It is worth noting that if Lumen is enabled, this leak does not occur. This is because AddLumenSceneData() is called during the rendering process, which successfully sets the ViewState->Scene pointer. However, when Lumen is disabled, the engine relies on a fallback initialization block inside FDeferredShadingSceneRenderer::Render(), which is guarded by the bRayTracing flag:

if (FamilyPipelineState[&FFamilyPipelineState::bRayTracing])
 
{
 
    for (FViewInfo& View : Views)
 
    {
 
       if (View.ViewState != nullptr)
 
       {
 
          if (View.ViewState->Scene == nullptr)
 
          {
 
             // link view state to the scene
 
             View.ViewState->Scene = Scene;
 
             Scene->ViewStates.Add(View.ViewState);
 
          }
 
       }
 
    }
 
}

Because I am not using Lumen or Ray Tracing, the capture’s ViewFamily evaluates bRayTracing to false, and the Scene pointer is never assigned. Consequently, when the ViewState is destroyed, it fails to unregister from the FRayTracingScene, leaking the scratch buffers allocated during dynamic updates.

Proposed Solution:

To fix this, the ViewState->Scene assignment needs to be uncoupled from the bRayTracing condition inside FDeferredShadingSceneRenderer::Render() so that any ViewState entering the pipeline guarantees its ability to clean itself up, regardless of whether Lumen or RT is active.

// Proposed Fix in FDeferredShadingSceneRenderer::Render()
 
for (FViewInfo& View : Views)
 
{
 
    if (View.ViewState != nullptr && View.ViewState->Scene == nullptr)
 
    {
 
        View.ViewState->Scene = Scene;
 
        Scene->ViewStates.Add(View.ViewState);
 
    }
 
}
 
 
 
if (FamilyPipelineState[&FFamilyPipelineState::bRayTracing])
 
{
 
    // ... remaining RT-specific pipeline logic
 
}

Questions for Support:

1. Can you confirm this is a known issue with how SceneCaptureComponent2D transient views interact with FRayTracingScene when bRayTracing is false and Lumen is disabled?

2. Is uncoupling the Scene pointer assignment from the bRayTracing check in Render() the safest engine-level fix, or are there unintended side effects for other rendering paths that rely on Scene being null in these conditions?

Thank you.

Reproduction Steps:

1. Attach a USceneCaptureComponent2D to a Pawn (or any actor with dynamic geometry).

2. Ensure Lumen and Ray Tracing are disabled for the capture view.

3. Constantly spawn and destroy/swap this Pawn in the world.

4. Observe STAT_RTAccelerationStructureMemory growing infinitely.

Hello,

Apologies for the delay, this issue was fixed yesterday (related PR) in CL#54300131 (4e652c) [HWRT] Fix leak RayTracingScene due to due view state not being linked to the scene when RendererOutput != ERendererOutput::FinalSceneColor.

UE 5.8 is CL#54297284 (66e7a4)