Description

Context: FMaterialPSORequestManager::PrecachePSOs() is called at runtime when an asset utilizing a material is loaded. This occurs during engine init, travel, and when any async or synchronous load occurs during normal ticking.

Problem: FMaterialPSORequestManager::PrecachePSOs() dynamically allocates a TStrongObjectPtr to pass to a FMaterialPSOPrecacheCollectionTask but that pointer is never freed by a corresponding FMaterialInterfaceReleaseTask like is done for other graph tasks dealing with materials in FMaterialPSORequestManager.

Steps to Reproduce
  1. Create a new project using one of the engine's simple sample projects (ex: Third Person).
  2. Package the project, and then run the packaged build.
  3. Attach the debugger as soon as possible with a breakpoint in FMaterialPSORequestManager::PrecachePSOs() where the FMaterialPSOPrecacheCollectionTask is created and dispatched.
  4. When the breakpoint is hit, put a memory breakpoint on the MaterialInterface TStrongObjectPtr.
  5. Continue execution, and see that the Object pointer within the TStrongObjectPtr is reset, but the heap-allocated TStrongObjectPtr itself never gets a deleted with a FMaterialInterfaceReleaseTask.
Callstack

Callstacks (non-fatal) for reference:

During engine init:

FMaterialPSORequestManager::PrecachePSOs(const FMaterialPSOPrecacheParams & Params, EPSOPrecachePriority Priority, TArray<TRefCountPtr<FBaseGraphTask>,TSizedInlineAllocator<4,32,TSizedDefaultAllocator<32>>> & OutGraphEvents) Line 286  C++
FMaterial::CollectPSOs(const TArray<FPSOPrecacheVertexFactoryData,TSizedInlineAllocator<2,32,TSizedDefaultAllocator<32>>> & VertexFactoryDataList, const FPSOPrecacheParams & PreCacheParams, EPSOPrecachePriority Priority, TArray<unsigned int,TSizedDefaultAllocator<32>> & OutMaterialPSORequestIDs) Line 3176  C++
UMaterial::PrecachePSOs(const TArray<FPSOPrecacheVertexFactoryData,TSizedInlineAllocator<2,32,TSizedDefaultAllocator<32>>> & VertexFactoryDataList, const FPSOPrecacheParams & InPreCacheParams, EPSOPrecachePriority Priority, TArray<unsigned int,TSizedDefaultAllocator<32>> & OutMaterialPSORequestIDs) Line 2975   C++
UMaterialInterface::PrecacheDefaultMaterialPSOs() Line 686  C++
FGlobalComponentRecreateRenderStateContext::~FGlobalComponentRecreateRenderStateContext() Line 522  C++
UGameEngine::Init(IEngineLoop * InEngineLoop) Line 1235 C++
FEngineLoop::Init() Line 4764   C++
EngineInit() Line 50    C++
GuardedMain(const wchar_t * CmdLine) Line 174   C++
GuardedMainWrapper(const wchar_t * CmdLine) Line 123    C++
LaunchWindowsStartup(HINSTANCE__ * hInInstance, HINSTANCE__ * hPrevInstance, char * __formal, int nCmdShow, const wchar_t * CmdLine) Line 277   C++
WinMain(HINSTANCE__ * hInInstance, HINSTANCE__ * hPrevInstance, char * pCmdLine, int nCmdShow) Line 335 C++
invoke_main() Line 102  C++
__scrt_common_main_seh() Line 288   C++
kernel32.dll!00007fff487ae8d7() Unknown
ntdll.dll!RtlUserThreadStart()  Unknown

During travel:

FMaterialPSORequestManager::PrecachePSOs(const FMaterialPSOPrecacheParams & Params, EPSOPrecachePriority Priority, TArray<TRefCountPtr<FBaseGraphTask>,TSizedInlineAllocator<4,32,TSizedDefaultAllocator<32>>> & OutGraphEvents) Line 286  C++
FMaterial::CollectPSOs(const TArray<FPSOPrecacheVertexFactoryData,TSizedInlineAllocator<2,32,TSizedDefaultAllocator<32>>> & VertexFactoryDataList, const FPSOPrecacheParams & PreCacheParams, EPSOPrecachePriority Priority, TArray<unsigned int,TSizedDefaultAllocator<32>> & OutMaterialPSORequestIDs) Line 3176  C++
UMaterial::PrecachePSOs(const TArray<FPSOPrecacheVertexFactoryData,TSizedInlineAllocator<2,32,TSizedDefaultAllocator<32>>> & VertexFactoryDataList, const FPSOPrecacheParams & InPreCacheParams, EPSOPrecachePriority Priority, TArray<unsigned int,TSizedDefaultAllocator<32>> & OutMaterialPSORequestIDs) Line 2975   C++
PrecacheMaterialPSOs(const TArray<FMaterialInterfacePSOPrecacheParams,TSizedInlineAllocator<4,32,TSizedDefaultAllocator<32>>> & PSOPrecacheParamsList, TArray<unsigned int,TSizedDefaultAllocator<32>> & OutMaterialPSOPrecacheRequestIDs, TArray<TRefCountPtr<FBaseGraphTask>,TSizedInlineAllocator<4,32,TSizedDefaultAllocator<32>>> & OutGraphEvents) Line 711   C++
UFXSystemAsset::LaunchPSOPrecaching(const TArray<FMaterialInterfacePSOPrecacheParams,TSizedInlineAllocator<4,32,TSizedDefaultAllocator<32>>> & PSOPrecacheParamsList) Line 46   C++
UNiagaraSystem::PrecachePSOs() Line 1507    C++
UNiagaraSystem::PostLoad() Line 1426    C++
UObject::ConditionalPostLoad() Line 1391    C++
FAsyncLoadingTickScope2::{ctor}(FAsyncLoadingThread2 & InAsyncLoadingThread) Line 5195  C++
FAsyncPackage2::Event_DeferredPostLoadExportBundle(FAsyncLoadingThreadState2 & ThreadState, FAsyncPackage2 * Package, int InExportBundleIndex) Line 9624    C++
FEventLoadNode2::Execute(FAsyncLoadingThreadState2 & ThreadState) Line 5979 C++
FAsyncLoadEventQueue2::ExecuteSyncLoadEvents(FAsyncLoadingThreadState2 & ThreadState) Line 6186 C++
FAsyncLoadingThread2::ProcessLoadedPackagesFromGameThread(FAsyncLoadingThreadState2 & ThreadState, bool & bDidSomething, TArrayView<int const ,int> FlushRequestIDs) Line 9935  C++
FAsyncLoadingThread2::TickAsyncLoadingFromGameThread(FAsyncLoadingThreadState2 & ThreadState, bool bUseTimeLimit, bool bUseFullTimeLimit, double TimeLimit, TArrayView<int const ,int> FlushRequestIDs, bool & bDidSomething) Line 10195    C++
FAsyncLoadingThread2::FlushLoading(TArrayView<int const ,int> RequestIDs) Line 11909    C++
FlushAsyncLoading(TArrayView<int const ,int> RequestIds) Line 356   C++
FlushAsyncLoading(int RequestId) Line 323   C++
LoadPackageInternal(UPackage * InOuter, const FPackagePath & PackagePath, unsigned int LoadFlags, FLinkerLoad * ImportLinker, FArchive * InReaderOverride, const FLinkerInstancingContext * InstancingContext, const FPackagePath * DiffPackagePath) Line 1716  C++
LoadPackage(UPackage * InOuter, const FPackagePath & PackagePath, unsigned int LoadFlags, FArchive * InReaderOverride, const FLinkerInstancingContext * InstancingContext, const FPackagePath * DiffPackagePath) Line 2079  C++
LoadPackage(UPackage * InOuter, const wchar_t * InLongPackageNameOrFilename, unsigned int LoadFlags, FArchive * InReaderOverride, const FLinkerInstancingContext * InstancingContext) Line 2055 C++
UEngine::LoadMap(FWorldContext & WorldContext, FURL URL, UPendingNetGame * Pending, FString & Error) Line 16032 C++
UEngine::Browse(FWorldContext & WorldContext, FURL URL, FString & Error) Line 15420 C++
UEngine::TickWorldTravel(FWorldContext & Context, float DeltaSeconds) Line 15618    C++
UGameEngine::Tick(float DeltaSeconds, bool bIdleMode) Line 1873 C++
FEngineLoop::Tick() Line 5829   C++
EngineTick() Line 60    C++
GuardedMain(const wchar_t * CmdLine) Line 190   C++
GuardedMainWrapper(const wchar_t * CmdLine) Line 123    C++
LaunchWindowsStartup(HINSTANCE__ * hInInstance, HINSTANCE__ * hPrevInstance, char * __formal, int nCmdShow, const wchar_t * CmdLine) Line 277   C++
WinMain(HINSTANCE__ * hInInstance, HINSTANCE__ * hPrevInstance, char * pCmdLine, int nCmdShow) Line 335 C++
invoke_main() Line 102  C++
__scrt_common_main_seh() Line 288   C++
kernel32.dll!00007fff487ae8d7() Unknown
ntdll.dll!RtlUserThreadStart()  Unknown

Have Comments or More Details?

There's no existing public thread on this issue, so head over to Questions & Answers just mention UE-361622 in the post.

0
Login to Vote

Unresolved
CreatedJan 21, 2026
UpdatedFeb 9, 2026
View Jira Issue