A crash may occur when changing the MaterialQualitylevel via Scalability due to a race condition.
The issue occurs because in ScalabilityCVarsSinkCallback(), when it creates the FGlobalComponentRecreateRenderStateContext, the constructor of it calls UpdateAllPrimitiveSceneInfosForScenes(). This launches a task on RenderThread which calls FPrimitiveSceneInfo::CacheMeshDrawCommands. This can the overlap with the assignment of GCachedScalabilityCVars which causes the issue.
This issue may be fixed by adding another FlushRenderingCommands() between creating the FGlobalComponentRecreateRenderStateContext and assigning GCachedScalabilityCVars here to wait for the UpdateAllPrimitiveSceneInfosForScenes RT work to finish.
Steps to Reproduce
1. Load into a map with many different materials using QualityLevel switch nodes and then change the MaterialQualityLevel via Scalability
Expected
Materials change without crashing
Actual
Sometimes the game will crash with the attached callstack
Game.exe!FMaterialShader::GetShaderBindings(const FSceneInterface * Scene, ERHIFeatureLevel::Type FeatureLevel, const FMaterialRenderProxy & MaterialRenderProxy, const FMaterial & Material, FMeshDrawSingleShaderBindings & ShaderBindings) Line 344 C++ Symbols loaded.
Game.exe!FMeshMaterialShader::GetShaderBindings(const FScene * Scene, ERHIFeatureLevel::Type FeatureLevel, const FPrimitiveSceneProxy * PrimitiveSceneProxy, const FMaterialRenderProxy & MaterialRenderProxy, const FMaterial & Material, const FMeshMaterialShaderElementData & ShaderElementData, FMeshDrawSingleShaderBindings & ShaderBindings) Line 467 C++ Symbols loaded.
Game.exe!TBasePassVertexShaderPolicyParamType<FUniformLightMapPolicy>::GetShaderBindings(const FScene *) Line 33 C++ Symbols loaded.
Game.exe!FMeshPassProcessor::BuildMeshDrawCommands<TMeshProcessorShaders<TBasePassVertexShaderPolicyParamType<FUniformLightMapPolicy>,TBasePassPixelShaderPolicyParamType<FUniformLightMapPolicy>,FMeshMaterialShader,FMeshMaterialShader,FMeshMaterialShader>,TBasePassShaderElementData<FUniformLightMapPolicy>>(const FMeshBatch & MeshBatch, unsigned __int64 BatchElementMask, const FPrimitiveSceneProxy * PrimitiveSceneProxy, const FMaterialRenderProxy & MaterialRenderProxy, const FMaterial & MaterialResource, const FMeshPassProcessorRenderState & DrawRenderState, const TMeshProcessorShaders<TBasePassVertexShaderPolicyParamType<FUniformLightMapPolicy>,TBasePassPixelShaderPolicyParamType<FUniformLightMapPolicy>,FMeshMaterialShader,FMeshMaterialShader,FMeshMaterialShader> & PassShaders, ERasterizerFillMode MeshFillMode, ERasterizerCullMode MeshCullMode, FMeshDrawCommandSortKey SortKey, EMeshPassFeatures MeshPassFeatures, const TBasePassShaderElementData<FUniformLightMapPolicy> & ShaderElementData) Line 139 C++ Symbols loaded.
Game.exe!FSingleLayerWaterPassMeshProcessor::Process(const FMeshBatch &) Line 1970 C++ Symbols loaded.
Game.exe!FSingleLayerWaterPassMeshProcessor::TryAddMeshBatch(const FMeshBatch &) Line 1925 C++ Symbols loaded.
Game.exe!FSingleLayerWaterPassMeshProcessor::AddMeshBatch(const FMeshBatch & MeshBatch, unsigned __int64 BatchElementMask, const FPrimitiveSceneProxy * PrimitiveSceneProxy, int StaticMeshId) Line 1901 C++ Symbols loaded.
Game.exe!FPrimitiveSceneInfo::CacheMeshDrawCommands::__l2::<lambda>(FCachedPassMeshDrawListContext & DrawListContext, int Index) Line 583 C++ Symbols loaded.
Game.exe!FPrimitiveSceneInfo::CacheMeshDrawCommands::__l8::<lambda>(int) Line 666 C++ Symbols loaded.
Game.exe!ParallelForImpl::CallBody(const FPrimitiveSceneInfo::CacheMeshDrawCommands::__l8::void <lambda>(void) &) Line 81 C++ Symbols loaded.
Game.exe!`ParallelForImpl::ParallelForInternal<`FPrimitiveSceneInfo::CacheMeshDrawCommands'::`8'::void <lambda>(void),`ParallelForTemplate<`FPrimitiveSceneInfo::CacheMeshDrawCommands'::`8'::void <lambda>(void)>'::`2'::void <lambda>(void),std::nullptr_t>'::`2'::FParallelExecutor::operator()(const bool bIsMaster) Line 360 C++ Symbols loaded.
Game.exe!LowLevelTasks::FTask::Init::__l13::<lambda>(const bool) Line 499 C++ Symbols loaded.
Game.exe!Invoke(LowLevelTasks::FTask::Init::__l13::void <lambda>(void) &) Line 47 C++ Symbols loaded.
Game.exe!LowLevelTasks::TTaskDelegate<LowLevelTasks::FTask * __cdecl(bool),48>::TTaskDelegateImpl<`LowLevelTasks::FTask::Init<`ParallelForImpl::ParallelForInternal<`FPrimitiveSceneInfo::CacheMeshDrawCommands'::`8'::void <lambda>(void),`ParallelForTemplate<`FPrimitiveSceneInfo::CacheMeshDrawCommands'::`8'::void <lambda>(void)>'::`2'::void <lambda>(void),std::nullptr_t>'::`2'::FParallelExecutor>'::`13'::void <lambda>(void),0>::Call(void *) Line 162 C++ Symbols loaded.
Game.exe!LowLevelTasks::TTaskDelegate<LowLevelTasks::FTask * __cdecl(bool),48>::TTaskDelegateImpl<`LowLevelTasks::FTask::Init<`ParallelForImpl::ParallelForInternal<`FPrimitiveSceneInfo::CacheMeshDrawCommands'::`8'::void <lambda>(void),`ParallelForTemplate<`FPrimitiveSceneInfo::CacheMeshDrawCommands'::`8'::void <lambda>(void)>'::`2'::void <lambda>(void),std::nullptr_t>'::`2'::FParallelExecutor>'::`13'::void <lambda>(void),0>::CallAndMove(LowLevelTasks::TTaskDelegate<LowLevelTasks::FTask * __cdecl(bool),48> & Destination, void * InlineData, unsigned int DestInlineSize, bool <Params_0>) Line 171 C++ Symbols loaded.
Game.exe!LowLevelTasks::TTaskDelegate<LowLevelTasks::FTask * __cdecl(bool),48>::CallAndMove(LowLevelTasks::TTaskDelegate<LowLevelTasks::FTask * __cdecl(bool),48> &) Line 309 C++ Symbols loaded.
Game.exe!LowLevelTasks::FTask::ExecuteTask() Line 627 C++ Symbols loaded.
Game.exe!FCpuProfilerTrace::FEventScope::
(unsigned int &) Line 197 C++ Symbols loaded.
Game.exe!LowLevelTasks::FScheduler::ExecuteTask(LowLevelTasks::FTask * InTask) Line 364 C++ Symbols loaded.
Game.exe!LowLevelTasks::FScheduler::TryExecuteTaskFrom(LowLevelTasks::Private::FWaitEvent *) Line 665 C++ Symbols loaded.
Game.exe!LowLevelTasks::FScheduler::WorkerLoop(LowLevelTasks::Private::FWaitEvent * WorkerEvent, LowLevelTasks::Private::TLocalQueueRegistry<1024,1024>::TLocalQueue * WorkerLocalQueue, unsigned int WaitCycles, bool bPermitBackgroundWork) Line 724 C++ Symbols loaded.
Game.exe!LowLevelTasks::FScheduler::WorkerMain(LowLevelTasks::Private::FWaitEvent * WorkerEvent, LowLevelTasks::Private::TLocalQueueRegistry<1024,1024>::TLocalQueue * WorkerLocalQueue, unsigned int WaitCycles, bool bPermitBackgroundWork) Line 783 C++ Symbols loaded.
Game.exe!LowLevelTasks::FScheduler::CreateWorker::__l2::<lambda>() Line 188 C++ Symbols loaded.
Game.exe!UE::Core::Private::Function::TFunctionRefBase<UE::Core::Private::Function::TFunctionStorage<1>,void __cdecl(void)>::operator()() Line 471 C++ Symbols loaded.
There's no existing public thread on this issue, so head over to Questions & Answers just mention UE-355606 in the post.
| 0 |
| Component | UE - Rendering Architecture - Materials |
|---|---|
| Affects Versions | 5.6 |
| Target Fix | 5.8 |
| Created | Nov 26, 2025 |
|---|---|
| Updated | Dec 1, 2025 |