UE 5.6 - Crash in strand hair due to unset shader parameter FParameters::BoneMatrices

We’re hitting a fatal ensure that we’re the shader parameter FParameters::BoneMatrices for FSkinUpdateCS is not set:

Fatal error: [File:D:\p4\dev\hopper\upgrade\Engine\Source\Runtime\RenderCore\Private\ShaderParameterStruct.cpp] [Line: 473] FSkinUpdateCS's required shader parameter FParameters::BoneMatrices was not set.When we try to set the BoneMatrices on the below line, BoneBuffer is null

Parameters->BoneMatrices = Sections[0].BoneBuffer;It looks to be null because in FSkeletalMeshDeformerHelpers::GetBoneBufferForReading we fail to retrieve the BaseVertexFactory

FGPUBaseSkinVertexFactory const* BaseVertexFactory = MeshObjectGPU->GetBaseSkinVertexFactory(InLodIndex, InSectionIndex); // <--- BaseVertexFactory is null here bool bHasBoneBuffer = BaseVertexFactory != nullptr && BaseVertexFactory->GetShaderData().HasBoneBufferForReading(bInPreviousFrame); if (!bHasBoneBuffer) { return nullptr; }This seems to be happening intermittently on transitions. Have there been any changes to lifetime management for these BaseVertexFactory objects? Are there any recommended preports for 5.6 that we should try?

I found a preport that (with slight modification) seems to fix this. Could I get eyes on my changes to the preport/a sanity check on if this is the right fix?

Our crash was actually in Card hair and not strand hair. I modified CL 42540266 to also apply its fix to card hair and that “solved” the crash. Code below:

`static FCachedGeometry GetCacheGeometryForHair(
FRDGBuilder& GraphBuilder,
FGlobalShaderMap* ShaderMap,
FSceneInterface* Scene,
FHairGroupInstance* Instance,
const FHairStrandsRestRootResource* RootResource,
const bool bOutputTriangleData,
const EHairPositionUpdateType PositionUpdateType,
FHairGeometryCache& OutHairGeometryCache)
{
FCachedGeometry Out;
if (const FPrimitiveSceneInfo* PrimitiveSceneInfo = GetMeshSceneInfo(Scene, Instance))
{
if (Instance->Debug.GroomBindingType == EGroomBindingMeshType::SkeletalMesh)
{
if (const FSkeletalMeshSceneProxy* SceneProxy = static_cast<const FSkeletalMeshSceneProxy*>(PrimitiveSceneInfo->Proxy))
{
// 1. Get cached geometry from GPU SkinCache, if enabled
const bool bValidCachedGeometry = SceneProxy->GetCachedGeometry(GraphBuilder, Out);
if (bValidCachedGeometry && Out.Sections.Num() > 0)
{
OutHairGeometryCache.AddDebug(Instance, SceneProxy, Out, PositionUpdateType, FHairGeometryCache::ECacheType::SkinCache);
}
// 2. If no cached geometry is extracted from the skel. mesh proxy, compute it using the manual hair skin cache
// Modification start
else if (bValidCachedGeometry && IsHairManualSkinCacheEnabled())
// Modification end
{
// Sync the async update tasks since we will be accessing bone buffers.
FSkeletalMeshUpdater::WaitForStage(GraphBuilder, ESkeletalMeshUpdateStage::SkinCache);

uint32 OutTotalSectionCount = 0;
GetOrAllocateCachedGeometry(GraphBuilder, ShaderMap, SceneProxy, RootResource, bOutputTriangleData, Out, OutHairGeometryCache, OutTotalSectionCount);
OutHairGeometryCache.AddDebug(Instance, SceneProxy, Out, PositionUpdateType, FHairGeometryCache::ECacheType::HairCache, OutTotalSectionCount);
}`

Hello!

Yes, I think this is fine. We have some fixes coming in the next patch for 5.6 which should address this if I recall correctly. Great you managed to solve the issue on your side!

/Charles.