Cooking indeterminism issues

Hey!

In our game we care about patches (in .pak file sense) being lean and containing only changes we expect, so I was investigating issues of cooking indeterminism (i.e. cooking the same unchanged asset twice resulting in different output files) and fixing them. Below are engine issues I’ve found and fixed. Maybe you can tell if fixes are okay or maybe I’ve misunderstood something?

UProceduralMeshComponent::ProcMeshBodySetup

We have some blueprints which create ProceduralMeshComponents on construction. Construction of procedural meshes is perfectly deterministic in all such cases but each time it’s constructed GUID of body setup is recreated, leading to indeterministic output. I replaced FGuid::NewGuid() with FGuid::NewDeterministicGuid(GetPathName()) which seems to be fine in this case.

FProcMeshSection::SectionLocalBox

This issue is just one of manifestation of more general bug: calculation of zero mask in unversioned property serialization is done by comparing memory representation of a property with zeros which is indeterministic if property contains padding bytes. In the case of UProceduralMeshComponent there is an issue with SectionLocalBox inside of ProcMeshSections. FBox has padding bytes so comparison memory with zero can fail. Trying to fix unversioned property serialization would be to much of a change so I added a crutch doing Memzero on SectionLocalBox in FProcMeshSection constructor, which is not exactly safe but does the job.

StaticMeshComponent::BodyInstance

I’ve found this issue in serialization of LevelSequence with StaticMeshActor with default collision for which mesh has NoCollision profile. The issue seems to be in the fact that in the case of default collision StaticMeshComponent loads collision parameters from mesh in UStaticMeshComponent::UpdateCollisionFromMesh method which is called only after mesh is compiled. So if component is being cooked before mesh is compiled then collision parameters are not loaded from mesh resulting in output being indeterministic. I’ve fixed it adding the following piece into UStaticMeshComponent::Serialize before Super::Serialize():

#if WITH_EDITOR
	if (Ar.IsCooking() && bUseDefaultCollision)
	{
		if (UStaticMesh* Mesh = GetStaticMesh())
		{
			if (Mesh->IsCompiling())
			{
				FStaticMeshCompilingManager::Get().FinishCompilation({ Mesh });
			}
		}
		UpdateCollisionFromStaticMesh();
	}
#endif

[Attachment Removed]

Thanks :slight_smile: The BodyInstance was one of the issue i observed as well in my project but didn’t investigate yet :slight_smile:

[Attachment Removed]

Hello!

UProceduralMeshComponent::ProcMeshBodySetup

The proposed change could be problematic if there are more than CVarBodySetupSkipDDCThreshold vertices (default 16384) in the body as this will use the DDC to store\retrieve the body. The problem is that the Mesh\Triangle content is not used in the DDC key for the body and the current code relies on the changing GUID to invalidate the DDC content. This could result in not using the right version of the BodySetup. I had Claude analyze the situation and I attached a summary of its findings so you can use it to proof your changes. The analysis was done on the Main stream so you might have to adapt it for 5.5.

I have also opened a bug report so this can be addressed in a future release of the engine. https://issues.unrealengine.com/issue/UE\-380849

FProcMeshSection::SectionLocalBox

CL43260457 addresses the padding bytes in FBox.

StaticMeshComponent::BodyInstance

The proposed fix appears fine for version 5.5 but an AI analysis outlined potential issues in future releases. I filed a bug report: https://issues.unrealengine.com/issue/UE\-380866

Regards,

Martin

[Attachment Removed]

May i ask, what is the issue to expect on later engine waiting on the mesh compilation for the cook (5.7) ? i’m testing it right now and it’s fixing the issue i was seeing

[Attachment Removed]

I validated the proposed changes on the current state of main in the context they were reported. It is possible that some of those points have been addressed through other ways. Lots of efforts were put in cooking determinism in relation to the work on Incremental cooking which could explain.

[Attachment Removed]

Thanks, yeah maybe it is already fixed on 5.8 or main, at least 5.7 still have that issue, good to know i can use this fix

[Attachment Removed]