[Lumen] Crash with 'Generate Distance Fields' in a packaged application

I’m trying to use Lumen Raytracing in a packaged build and without hardware acceleration. In order for this to work software-only we need to calculate distance fields, which are accessible and fully working in Editor. Using them in a packaged build causes a crash.

Platforms: Windows and Mac.

Crash log:
crash_log.rtf (155.8 KB)

Is there any workaround? Is this supposed to work in a packaged application?

2 Likes

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.

1 Like