Hi,
We encountered this crash in our game project using UE 5.5. We made some code changes in the engine, but nothing related to low-level rendering nor ray tracing.
We investigated the issue last week and made some progress.
When ray tracing is enabled, bindless descriptor heaps will be used for ray tracing. Material will create uniform buffers which are cached by the rendering thread and bind for ray tracing by RHI thread. But rendering thread and RHI thread does not affect the lifetime of uniform buffer by managing its reference count, instead, code will pass the raw pointers around. So, it is critical that material cannot release its uniform buffer until rendering thread finishes the access of uniform buffer.
`void SetShaderMapsOnMaterialResources_RenderThread(FRHICommandListImmediate& RHICmdList, FMaterialsToUpdateMap& MaterialsToUpdate)
{
// Async RDG tasks can call FMaterialShader::SetParameters which touch the material uniform expression cache.
FRDGBuilder::WaitForAsyncExecuteTask();`
But this code is not sufficient for ray tracing, because when binding the resource for ray tracing, the access of resource table and uniform buffers are further delayed to the RHI command running on the RHI thread.
void FRHICommandSetBindingsOnShaderBindingTable::Execute(FRHICommandListBase& CmdList) { INTERNAL_DECORATOR(RHISetBindingsOnShaderBindingTable)(SBT, RayTracingPipelineState, NumBindings, Bindings, BindingType);
The crash is caused by the fact that material uniform buffer is released before RHI command is executed.
When a material or a texture is modified by FShaderCompilingManager or FTextureCompilingManager, game thread will recreate the render state with following code
for (IPrimitiveComponent* AffectedPrimitive : AffectedPrimitives) { AffectedPrimitive->MarkRenderStateDirty(); }
In theory, this code will destroy old rendering state and create a new rendering state. The cached ray tracing draw commands will be removed and recreated in the process. But two things are interfering
- The recreation is further delayed to the EndOfFrameUpdate in game thread
- The update in the rendering thread is not a complete update when component is destroyed and created in same frame
SceneUpdateChangeSetStorage.PrimitiveUpdates.ForEachCommand([&](const FPrimitiveUpdateCommand& Cmd) { // Skip those that were added & removed in the same frame if (Cmd.IsAdd() && !Cmd.IsDelete()) { SceneUpdateChangeSetStorage.AddedPrimitiveSceneInfos.Add(Cmd.GetSceneInfo()); } if (Cmd.IsDelete()) { DeletedPrimitiveSceneInfos.Add(Cmd.GetSceneInfo()); // Skip those that were added & removed in the same frame if (!Cmd.IsAdd()) { SceneUpdateChangeSetStorage.RemovedPrimitiveSceneInfos.Add(Cmd.GetSceneInfo()); SceneUpdateChangeSetStorage.RemovedPrimitiveIds.Add(Cmd.GetPersistentId()); } }
This is what we have found so far. We have not found any workaround for the issue. We may have to disable the ray tracing to prevent the crash in Editor.
Thanks,
Yichen Wang