One source of non-determinism in the cooked output is UMaterialInterface::Serialize function updating the bIncludedInBaseGame field. If the material being serialized has an object in a different package as archetype (eg a level being cooked, and archetype in a blueprint), then:
- if blueprint is cooked first, by the time the level is cooked, the bIncludedInBaseGame in level’s object and archetype will both be true, and delta-serialization would not serialize the value
- if level is cooked first, the bIncludedInBaseGame for level’s object and the archetype will be different, and delta-serialization would serialize the field
Now, I don’t really understand the purpose of this field - it’s only used in a UMaterialInstance::IsStaticPermutationAllowedForCandidateParent function, and even then only if bEnableRestrictiveMaterialInstanceParents is true; the bEnableRestrictiveMaterialInstanceParents is initialized to false and never written. This makes me think the field can be removed safely?
If not, I believe the correct way to handle that would be to serialize it manually in the Serialize function, and then mark it as transient to make the default property serialization ignore it.