To add more context, the crash happens when creating a dynamic mesh component at runtime from C++ with distance field mode set to ‘EDynamicMeshComponentDistanceFieldMode::AsyncCPUDistanceField’ and ‘Generate Mesh Distance Fields’ ticked in the project settings.
The crash can be reproduced in a blank project with a simple triangle mesh and hardware ray tracing disabled. Here is a code snippet showing how the mesh was created:
UDynamicMeshComponent* DynamicMeshComp = NewObject<UDynamicMeshComponent>(this, UDynamicMeshComponent::StaticClass(), NAME_None, RF_Transient);
DynamicMeshComp->SetupAttachment(DynamicMeshesComp);
DynamicMeshComp->SetDistanceFieldMode(EDynamicMeshComponentDistanceFieldMode::AsyncCPUDistanceField);
DynamicMeshComp->SetMeshDrawPath(EDynamicMeshDrawPath::DynamicDraw);
DynamicMeshComp->RegisterComponent();
FDynamicMesh3 Mesh;
int32 Vertex0 = Mesh.AppendVertex(FVector3d(0.0, 0.0, 0.0));
int32 Vertex1 = Mesh.AppendVertex(FVector3d(100.0, 0.0, 0.0));
int32 Vertex2 = Mesh.AppendVertex(FVector3d(0.0, 100.0, 0.0));
Mesh.AppendTriangle(Vertex1, Vertex0, Vertex2);
DynamicMeshComp->GetDynamicMesh()->SetMesh(Mesh);
DynamicMeshComp->SetMobility(EComponentMobility::Movable);
DynamicMeshComp->RecreateRenderState_Concurrent();
The crash happens regardless of whether using ‘EDynamicMeshDrawPath::DynamicDraw’ or ‘EDynamicMeshDrawPath::StaticDraw’ as the argument to ‘SetMeshDrawPath’ function.
Looking at the crash log a null pointer is dereferenced inside FDistanceFieldSceneData::AsyncUpdate(FRHICommandListBase& RHICmdList, FDistanceFieldAsyncUpdateParameters& UpdateParameters) function. Here is a snippet of that function where the crash occurs:
for (FDistanceFieldReadRequest& ReadRequest : UpdateParameters.NewReadRequests)
{
check(ReadRequest.BulkSize > 0);
ReadRequest.ReadOutputDataPtr = (uint8*)FMemory::Malloc(ReadRequest.BulkSize);
const bool bIODispatcher = ReadRequest.BulkData->IsUsingIODispatcher();
if (bIODispatcher)
{
// Use IODispatcher when available
FIoChunkId ChunkID = ReadRequest.BulkData->CreateChunkId();
FIoReadOptions ReadOptions;
ReadOptions.SetRange(ReadRequest.BulkData->GetBulkDataOffsetInFile() + ReadRequest.BulkOffset, ReadRequest.BulkSize);
ReadOptions.SetTargetVa(ReadRequest.ReadOutputDataPtr);
ReadRequest.Request = Batch.Read(ChunkID, ReadOptions, IoDispatcherPriority_Low);
}
else
{
// Compatibility path without IODispatcher
ReadRequest.AsyncHandle = ReadRequest.BulkData->OpenAsyncReadHandle();
ReadRequest.AsyncRequest = ReadRequest.AsyncHandle->ReadRequest(ReadRequest.BulkData->GetBulkDataOffsetInFile() + ReadRequest.BulkOffset, ReadRequest.BulkSize, AIOP_Low, nullptr, ReadRequest.ReadOutputDataPtr);
}
}
A null pointer is returned from
ReadRequest.BulkData->OpenAsyncReadHandle();
inside the else block. The crash then occurs on the next line of code where ‘ReadRequest.AsyncHandle’ is assumed to be a non null pointer.