Is streaming in traditional static mesh LODs supposed to be working?

We noticed that LODs from all traditional static meshes in our scene are fully resident. We’ve configured LOD groups that should allow them to be streamed in as needed, like mips for textures. When digging into the streaming manager to see what’s going on, I noticed FAsyncRenderAssetStreamingData::UpdatePerfectWantedMips_Async using the unknown ref hueristic. This happened because UStaticMesh doesn’t implement GetLastRenderTimeForStreaming (which returns FLT_MAX by default), so using this path will cause it to request all LODs in the end of the function when it calls FStreamingRenderAsset::SetPerfectWantedMips_Async. Otherwise, it seems like it can individually load LODs in the pipeline, its just forced to load them all.

By all other accounts in the codebase, it looks like it should support streaming in of LODs but I can find no detailed documentation over this. There is an option in the LOD settings of the static mesh called “Num Streamed LODs” that seem pertinent to avoid inlining the LODs with the asset, and UE seems to have platforms be able to be queried if they support mesh LOD streaming. It is confusing to me that the codebase seems to indicate that it should be supported, but it functionally doesn’t seem like it works.

The repro project should mimic the settings we used on our LOD streaming meshes.

Steps to Reproduce
Package the project and run it, hook into FRenderAssetStreamingMipCalcTask::DoWork and observe it eventually requesting all LODs for the mesh.

Hi Ali,

I took a quick look at the project. What I found is that when I:

  1. Add “r.MeshStreaming=True” to the [/Script/Engine.RendererSettings] of DefaultEngine.ini, and
  2. Set “Num Streamed LODs” on a static mesh (I set the value to 4 on SM_LODTest)

Then mesh LOD streaming works in a cooked build.

For point 2 you should be able to set DefaultMaxNumStreamedLODs on your mesh LOD group instead.

Best regards,

Jeremy

Thank you for providing corrections to the sample project, I have applied them and reuploaded with this post. I’ve just only missed these settings for the sample project, they are present in our studio project.

However, if you use the ListStaticMeshes command, it will still show all the LODs are fully resident. I am unable to do verify through hooking into FRenderAssetStreamingMipCalcTask::DoWork as I’m not sure how to hook my debugger into engine code in a sample project besides from packaging/compiling the engine along side it, but our project does not have any modifications to streaming code and shows it gathering all LODs for the static mesh despite having all the correct settings for streaming LODs.

MeshLODStreamRepro.zip(3.11 MB)

Hi Ali,

I took a look at the latest version of the project. I think your asset needs to be assigned a LODGroup that has bSupportLODStreaming=true.

It currently has no LODGroup assigned so that it will take the default value for FStaticMeshLODGroup::bSupportLODStreaming which is false.

Alternatively you can LODStreaming=Enabled on the asset, instead of the current setting which is LODStreaming=Default (default to LODGroup setting).

That should fix things. Then you can use “TrackRenderAsset <your asset name>” on the console to track streaming events.

Also it is sometimes helpful to do “r.Streaming.StressTest 1” to force streaming in and out to happen every few frames and test that it works.

If you do work out a way hook up your debugger, some useful breakpoint locations are:

UStreamableRenderAsset::LinkStreaming() to see whether streaming is set for your asset at startup.

UStaticMesh::StreamIn() and UStaticMesh::StreamOut() to break on streaming events.

Best regards,

Jeremy