I know HISMs are on the way out but our project relies heavily on dense foliage (30k+ instances per cell) and we are seeing spikes on lower end hardware of up to 10-15ms when foliage is loaded via world partition and can observe spikes of 2-5ms on high end hardware too.
Initially I thought our use of Custom Instance data was to blame but I’ve managed to track this back to UHierarchicalInstancedStaticMeshComponent::GetInstanceTransforms and the work after it in UHierarchicalInstancedStaticMeshComponent::BuildTreeAsync
I’ve tried to just return out of BuildTreeAsnyc immediately as a hail Mary and at first glance it does not seem to break anything. I’m assuming there might be some deeper implications if we completely skip all this work.
I’ve tried to just return out of BuildTreeAsnyc immediately as a hail Mary and at first glance it does not seem to break anything. I’m assuming there might be some deeper implications if we completely skip all this work.
Are you calling ApplyEmpty() to reset the flags? I’d check if BuildTree is getting called at some point and after BuildTreeAsync would normally run and is fixing up the results somehow.
In UE 5.6, we introduced the FastGeo Plugin which is built on WP cell transformers to improve async loading of static instances. If your instances are immutable and can be converted from HISMC to ISMC this can be a good option here and is generally what we recommend in our Level Streaming Hitching Guide. Instructions on enabling and using FastGeo can be found in our World Building Guide.
Apologies for the delay, I think this is actually a bug that is a side effect of CL#29842762 in which BuildTreeIfOutdated was updated to run when PrimitiveInstanceDataManager.HasAnyChanges(), which seems to always be the case at runtime when loading a world partition cell, but BuildTreeIfOutdated wouldn’t call BuildTreeAsync before this change. If you revert this change the foliage HISM will still render as expected at runtime without the spike caused by rebuilding the cluster tree but there may be additional side effects.
I’ve created the following issue which should be visible publicly soon for tracking:
Apologies for the delay. Can you provide more details about how BuiltTreeAsync is called via OnPostLoadPerInstanceData() in the standalone game? It isn’t supposed to be called unless somehow the tree has been modified at runtime.
Yes, if the foliage density scaling is below 1.0 at runtime this can cause a tree rebuild during loading (from UHierarchicalInstancedStaticMeshComponent::OnPostLoadPerInstanceData())
Thanks for the pointers I’ll have a look around see if there’s anything in the guides that can help us.
At the moment I’m literally just returning out of the function immediately so it’s super crude. I’ll try your suggestions and see where I get.
FastGeo is being investigated by the engineering team, though we’re running into some crashes here and there so in the short term I can’t rely on that as a fix.
Are you callingApplyEmpty*() to reset the flags? I’d check ifBuildTreeis getting called at some point and afterBuildTreeAsyncwould normally run and is fixing up the results somehow.*
I’m not sure I understand. ApplyEmpty() just wipes the instances and they no longer render. BuildTree() BuildTreeAsync() both take ages to process this many instances.
If I disable both functions it can cause instances to not render after loading a level and in editor when painting new foliage, but disabling BuildTreeAsync() alone and only in game seems to behave correctly outside of density scaling not updatinganymore.
Thanks for the pointers, unfortunately it didn’t seem to help with the spikes,
UHierarchicalInstancedStaticMeshComponent::OnPostLoadPerInstanceData() forces a BuildTreeAsync regardless of those checks it looks like.
Instance HLODs also seem to cause similar spikes, though I’ve only noticed it recently while testing for this.
Currently my only semi-viable option seems to be to bypass BuildTreeAsync in game and keep it around for editor use as that’s where I’ve noticed it causing issues when paining foliage or when new instance foliage components are added.
We are using density scaling so that’s likely part of the problem and after more thorough testing skipping the Tree Build caused similar issues to the old Density Scaling <--> WPO disable distance bug with instances becoming huge and stretched.
I think we can mark this as resolved for now, we know where the issue is coming from and we can try and find a way around it.