UE5 FGPUSkinCache::ProcessEntry() Crash

Crash堆栈如下:

[2025.09.01-13.09.01:400][290]LogWindows: Error: === Critical error: ===

[2025.09.01-13.09.01:400][290]LogWindows: Error:

[2025.09.01-13.09.01:400][290]LogWindows: Error: Assertion failed: !AllocationFlags[Index] [File:D:\Gitlab\unrealengine\Engine\Source\Runtime\Core\Public\Containers\SparseArray.h] [Line: 111]

[2025.09.01-13.09.01:400][290]LogWindows: Error:

[2025.09.01-13.09.01:400][290]LogWindows: Error:

[2025.09.01-13.09.01:400][290]LogWindows: Error:

[2025.09.01-13.09.01:400][290]LogWindows: Error: [Callstack] 0x00007ff619c429ad Product.exe!TSparseArray<TSetElement<FGPUSkinCacheEntry * __ptr64>,TSparseArrayAllocator<TSizedDefaultAllocator<32>,FDefaultBitArrayAllocator> >::AllocateIndex()

[2025.09.01-13.09.01:400][290]LogWindows: Error: [Callstack] 0x00007ff619c1da76 Product.exe!TSet<FGPUSkinCacheEntry * __ptr64,DefaultKeyFuncs<FGPUSkinCacheEntry * __ptr64,0>,FDefaultSetAllocator>::Emplace<FGPUSkinCacheEntry * __ptr64 const & __ptr64>()

[2025.09.01-13.09.01:400][290]LogWindows: Error: [Callstack] 0x00007ff619ca353b Product.exe!FGPUSkinCache::ProcessEntry()

[2025.09.01-13.09.01:400][290]LogWindows: Error: [Callstack] 0x00007ff61a745d7a Product.exe!FSkeletalMeshObjectGPUSkin::ProcessUpdatedDynamicData()

[2025.09.01-13.09.01:400][290]LogWindows: Error: [Callstack] 0x00007ff61a759329 Product.exe!FSkeletalMeshObjectGPUSkin::UpdateDynamicData_RenderThread()

[2025.09.01-13.09.01:400][290]LogWindows: Error: [Callstack] 0x00007ff61a6fee9c Product.exe!FSoundAttenuationSettings::operator==()

[2025.09.01-13.09.01:400][290]LogWindows: Error: [Callstack] 0x00007ff617c239ce Product.exe!FRenderCommandPipe::ExecuteCommand()

[2025.09.01-13.09.01:400][290]LogWindows: Error: [Callstack] 0x00007ff617c08e29 Product.exe!`FBatchedReleaseResources::Flush’::`5’::<lambda_1>::operator()()

[2025.09.01-13.09.01:400][290]LogWindows: Error: [Callstack] 0x00007ff6131d45f3 Product.exe!UE::Tasks::Private::FTaskBase::TryExecuteTask()

[2025.09.01-13.09.01:400][290]LogWindows: Error: [Callstack] 0x00007ff6131a75ff Product.exe!LowLevelTasks::TTaskDelegate<LowLevelTasks::FTask * __ptr64 __cdecl(bool),48>::TTaskDelegateImpl<`LowLevelTasks::FTask::Init<`UE::Tasks::Private::FTaskBase::Init’::`2’::<lambda_1> >‘::`13’::<lambda_1>,0>::CallAndMove()

[2025.09.01-13.09.01:400][290]LogWindows: Error: [Callstack] 0x00007ff6131b270e Product.exe!LowLevelTasks::FTask::ExecuteTask()

[2025.09.01-13.09.01:400][290]LogWindows: Error: [Callstack] 0x00007ff6131b248b Product.exe!LowLevelTasks::FScheduler::ExecuteTask()

[2025.09.01-13.09.01:400][290]LogWindows: Error: [Callstack] 0x00007ff6131d7bcd Product.exe!LowLevelTasks::FScheduler::WorkerLoop()

[2025.09.01-13.09.01:400][290]LogWindows: Error: [Callstack] 0x00007ff6131a0181 Product.exe!`FScopeCycleCounter::~FScopeCycleCounter’::`2’::<lambda_1>::operator()()

[2025.09.01-13.09.01:400][290]LogWindows: Error: [Callstack] 0x00007ff6133a0d33 Product.exe!FThreadImpl::Run()

[2025.09.01-13.09.01:400][290]LogWindows: Error: [Callstack] 0x00007ff6137c4f68 Product.exe!FRunnableThreadWin::Run()

[2025.09.01-13.09.01:400][290]LogWindows: Error: [Callstack] 0x00007ff6137bc5cf Product.exe!FRunnableThreadWin::GuardedRun()

[2025.09.01-13.09.01:400][290]LogWindows: Error: [Callstack] 0x00007ffd29177374 KERNEL32.DLL!UnknownFunction

[2025.09.01-13.09.01:400][290]LogWindows: Error:

[2025.09.01-13.09.01:400][290]LogWindows: Error: Crash in runnable thread Foreground Worker #

Crash 在 PendingProcessRTGeometryEntries.Add(InOutEntry) 这一句

bool FGPUSkinCache::ProcessEntry()
{
  ……
#if RHI_RAYTRACING
      if (!Skin->ShouldUseSeparateSkinCacheEntryForRayTracing() || Mode == EGPUSkinCacheEntryMode::RayTracing)
    {
       // This is a RT skin cache entry
       PendingProcessRTGeometryEntries.Add(InOutEntry);
    }
#endif
 
    return true;
}

<br/>

经调试发现该函数会被多个工作线程执行,

结合crash 堆栈,应该是多线程同时执行 PendingProcessRTGeometryEntries.Add(InOutEntry) 导致的,

目前加了个锁临时保护了下,如下

if (!Skin->ShouldUseSeparateSkinCacheEntryForRayTracing() || Mode == EGPUSkinCacheEntryMode::RayTracing)
{
    FScopeLock Lock(&GPUSkinCacheEntrySetLock);
    // This is a RT skin cache entry
    PendingProcessRTGeometryEntries.Add(InOutEntry);
}

因为此行代码每帧都执行,不知是否合适,

期待官方的正式解决方案

重现步骤
UE版本 5.5.4,跑游戏偶现Crash,这阵子出现过几次

Hi,

我不太确定,因为我的理解是虽然UpdateDynamicData_RenderThread可以跑在异步线程,但是是所有的SkeletalMesh跑在同一个RenderCommandPipe上,也就是同一个线程上,所以理论上不会多线程写入这个TSet。

我在内部也没有看到跟你情况相同的报错,你能确认一下是多个线程同时UpdateDynamicData_RenderThread,而不是同一个worker thread吗?

用 UnrealInsights 录制能看到同一帧内在两个线程跑 UpdateDynamicData_RenderThread,这个信息是否有效?

[Image Removed]

感谢提供信息,​我猜很可能是TaskGraph的Retraction功能,导致渲染线程在等待任务结束的时候,发现任务还没有执行,就拿过来执行了,就导致多个任务并行。你可以试试设置r.RenderCommandPipeMode=1。

好的,我们改了观察一阵子​

我把问题反馈给开发团队,但是他们还是不太相信并行的情况,从UnrealInsight里,只能表示这些任务会执行在不同的线程上,但是应该是顺序执行的 (LastTask的依赖是上一个LastTask),所以应该也不存在并行的情况,因为这个功能已经存在至少两年时间了,之前没有人遇到过类似的情况,但也不排除发生概率非常低。

可以先试试上面的设置,然后看一下是否有改善。当然如果能找到一个相对稳定的复现方式,应该会更有帮助。[Image Removed]

理解了,不会并行的话确实不该出现这个堆栈,可能是其他因素导致的,我们后续继续观察研究

好的,如果后续有什么线索,可以跟我说一下,感谢。