【概要】
Naniteが有効なStaticMeshにおいて、InitResourcesとReleaseResourcesで計算されるリソースサイズに乖離があるため、統計値(STAT_StaticMeshTotalMemory)が正しく減算されず、デバッグ表示上でメモリリークが発生しているように見える現象を確認しました。
調査の結果、Naniteリソースの一部が解放処理の過程で先に破棄またはサイズ変更されているために、GetResourceSizeBytes が返す値が確保時よりも小さくなっていることが原因と推測されます。
【再現環境】
UEバージョン: 5.7.3 (Source Build)
プラットフォーム: Windows Package (Developmentビルドで確認。EditorPIE実行、StandAlone実行では確認できませんでした。)
対象: Naniteサポートを有効化したStaticMeshが存在するレベルをロード・アンロード(調査環境ではOpenLevelでレベル遷移を行うだけで発生しました)
【調査内容】
StaticMesh.cpp の実装を確認したところ、以下の箇所で統計値の加減算が行われています。
確保時:UStaticMesh::InitResources()
GetResourceSizeBytes(EResourceSizeMode::Exclusive) で取得したサイズを INC_DWORD_STAT_BY で加算。
解放時:UStaticMesh::ReleaseResources()
同様に GetResourceSizeBytes(EResourceSizeMode::Exclusive) で取得したサイズを DEC_DWORD_STAT_BY で減算。
しかし、Nanite有効なメッシュで検証したところ、以下の通りサイズに差分が生じていました。(メッシュはどのメッシュでもNaniteサポートが有効になっている場合は同様に現象を確認できます。)
InitResources時:
TotalSize: 81,492 (Naniteリソース分: 33,488 / その他: 48,004)
ReleaseResources時:
TotalSize: 48,324 (Naniteリソース分: 320 / その他: 48,004)
非Nanite部分のサイズは一致していますが、Naniteリソース(RootData, PageStreamingStates等)のサイズが、ReleaseResources が呼ばれるタイミングでは既に大幅に減少あるいは一部破棄されています。
この結果、加算した値よりも少ない値が減算されるため、レベルのロード/アンロードを繰り返すたびに STAT_StaticMeshTotalMemory の値が累積し、統計上リークしているように見えてしまいます。
Naniteに関しては
NaniteResource.cpp
void FResources::SerializeInternal(FArchive& Ar, UObject* Owner, bool bCooked)
でStremablePagesにシリアライズされており、RenderThread側で処理されているのかと思われます。
【検証ログ】
~初期化時
[2026.02.16-06.18.42:420][739]LogStaticMesh: Warning: [Ptr:0000018481BCD5D0]->NowSize[0]::UStaticMesh::Serialize
[2026.02.16-06.18.42:421][739]LogStaticMesh: Warning: [Ptr:0000018481BCD5D0]->NowSize[0]::UStaticMesh::SetRenderData
[2026.02.16-06.18.42:421][739]LogStaticMesh: Warning: [Ptr:0000018481BCD5D0]->NowSize[81492]::UStaticMesh::SetRenderData
[2026.02.16-06.18.42:421][739]LogStaticMesh: Warning: [Ptr:0000018481BCD5D0]->NowSize[81492]::UStaticMesh::UpdateStaticMaterialsInfoCache
~解放時
[2026.02.16-06.18.45:413][483]LogStaticMesh: Warning: [Ptr:0000018481BCD5D0]->NowSize[48324]::UStaticMesh::BeginDestroy
[2026.02.16-06.18.45:413][483]LogStaticMesh: Warning: [Ptr:0000018481BCD5D0]->NowSize[48324]::UStaticMesh::ReleaseResources
[2026.02.16-06.18.45:413][483]LogStaticMesh: Warning: [Ptr:0000018481BCD5D0]->NowSize[48324]::UStaticMesh::BeginDestroy
[2026.02.16-06.18.45:413][483]LogStaticMesh: Warning: [Ptr:0000018481BCD5D0]->NowSize[48324]::UStaticMesh::IsReadyForFinishDestroy
NaniteResourceSizeも表示したログは下記の通りでした。
[2026.02.16-08.28.03:942][714]LogStaticMesh: Warning: [Ptr:0000022855F35CE0]->NowSize[81492]->NaniteSize[33488]::UStaticMesh::InitResources
[2026.02.16-08.28.06:922][477]LogStaticMesh: Warning: [Ptr:0000022855F35CE0]->NowSize[48324]->NaniteSize[320]::UStaticMesh::ReleaseResources
Naniteのサイズ取得のログの出力は以下で行っております。
FResourceSizeEx ResSize = FResourceSizeEx(EResourceSizeMode::Exclusive);
GetResourceSizeEx(ResSize);
UE_LOG(LogTemp, Warning, TEXT("[Ptr:%p]->NaniteSize[%llu]::%s"), (const void*)this, ResSize.GetTotalMemoryBytes(), *FString(__FUNCTION__));
【質問】
・統計上の不一致か、メモリリークか
DEC_DWORD_STAT_BYに渡されるサイズが小さいため、Debug View上の StaticMeshTotalMemory は増加し続けます。これは単なる表示上のバグ(統計計算のタイミングの問題)でしょうか、それともNaniteリソースの実際の解放漏れが発生しているのでしょうか。
・Naniteのメモリ管理仕様:
Naniteリソースは StreamablePages 等を通じてGPU/レンダリスレッド側で管理されている認識でございますが、ReleaseResources時点でGetResourceSizeBytesが小さい値を返すのは意図された挙動でしょうか。
もし統計上の問題である場合、確保時のサイズを保持しておいて減算するような修正が適切でしょうか。あるいは、Naniteリソースのサイズ取得において推奨されるタイミングや手法があればご教授ください。
以上、よろしくお願いいたします。
[Attachment Removed]