SplineMeshComponentを使用しているサブレベルのロード、アンロードを繰り返すとRHIResourceがリークしてしまう

お世話になっております。

<br/>

現在マップにフェンスなどを配置する際にSplineに合わせて配置するためSplineMeshComponentを使用しているのですが

SplineMeshComponentを使用しているサブレベルのロード、アンロードを繰り返すと登録したStaticMeshの一部LODのRHIResourceがリークしてしまっていることが判明しました。

<br/>

SplineMeshComponent使い方としては

BPのConstructionScriptにてSplineのセグメント数に応じてSplineMeshComponentをAddComponentし

そこに配置したBP側で指定したStaticMeshを登録する形になっています。

[Image Removed]

<br/>

こちらサブレベルのアンロード時に正しく解放されるようにする方法はありますでしょうか?

よろしくお願いいたします。

<br/>

<br/>

[Attachment Removed]

再現手順
1.添付したプロジェクトをWindows向けにパッケージ化します

2.起動して1キーを押すとSplineMeshComponentを使用しているサブレベル(LV_2)をロードして表示します

3.2キーを押すとLV_2を非表示にしてアンロードし、その後SplineMeshComponentを使用している別のサブレベル(LV_3)をロードして表示します

​4.3キーを押すとLV_3を非表示にしてアンロードし、その後LV_2をロードして表示します

​5.この状態でコンソールコマンドから「rhi.DumpResourceMemory all -csvfile」を入力し​出力されたcsvにLV_3にしか登録されていないStaticMeshののBufferが残ってしまっていることがあるのを確認します

添付したプロジェクトでは​

obj listにも含まれない​「SM_RailRig_Mount」か「SimplePivotPainterExample」のBufferが残り続けているのが確認できます

また、2キー、3キーを何度も交互に押すことでこれらのBufferは増加します​

[Image Removed]

[Attachment Removed]

再現プロジェクトおよび詳しい調査ありがとうございます。

リークが確認できました。

問題は複数スレッドから並列で呼び出される InitSplineVertexFactory_Internalは初期化済み(VertexFactories.SplineVertexFactory!=nullptr)であればスキップされますが、同時に複数の初期化が行われるとき、

FSplineMeshVertexFactory* VertexFactory = new FSplineMeshVertexFactory(FeatureLevel);の行が複数のスレッドから同時に処理されてそのあと同一メモリに書き出される点にあり、最後に書き込まれたリソース以外はリークしてしまいます。

対策として同期オブジェクトで排他制御することで改善が見られました。以下のコードをお試しいただけますでしょうか。

(CriticalSectionは対応するリソースに対して宣言された方が適切かもしれませんが、メモリへのインパクトもあるのでグローバル変数としました。)

static FCriticalSection GInitSplineVertexFactoryCS;  //追加
 
static void InitSplineVertexFactory_Internal(FStaticMeshVertexFactories& VertexFactories, const FStaticMeshVertexBuffers& VertexBuffers, int32 LightMapCoordinateIndex, const ERHIFeatureLevel::Type FeatureLevel, FColorVertexBuffer* InOverrideColorVertexBuffer)
{
	// Skip LODs that have their render data stripped (eg. platform MinLod settings)
	if (VertexBuffers.StaticMeshVertexBuffer.GetNumVertices() == 0)
	{
		return;
	}
 
	bool bOverrideColorVertexBuffer = !!InOverrideColorVertexBuffer;
 
	FScopeLock Lock(&GInitSplineVertexFactoryCS); //追加
 
	if ((VertexFactories.SplineVertexFactory && !bOverrideColorVertexBuffer) || (VertexFactories.SplineVertexFactoryOverrideColorVertexBuffer && bOverrideColorVertexBuffer))
 
 

[Attachment Removed]

最新のUE5.8でも同様のバグが発生することを確認し、本件を UE-389807 SplineMeshComponent resources leak としてバグ登録させていただきました。

[Attachment Removed]

お世話になっております

こちらのCriticalSection追加対応を行うことでリソースがリークしなくなっているのを確認できました

一旦この方法で様子を見ようと思います。

ありがとうございました。​

ただ、これが原因だと思っていた現象で

サブレベルのロード/アンロードを行ったときにShaderResourceMemoryが増加し続ける

というのもがあるのですが​今回の対応では改善されませんでした

こちらに関しては別で質問を投げさせていただこうかと思います。 [Image Removed]

[Attachment Removed]