Textures may load highest mip during FlushAsyncLoad regardless of actual rendering stats

Hi,

While trying to fit our title into Xbox Series S memory, I ran into a weird issue, where occasionally, texture memory would spike massively for no reason. In our project, this means more than 1 GiB of texture allocations for one single frame.

[Image Removed]

In our project this seems to happen occasionally when a player fast-travels to a new location, meaning it could potentially crash the game with an OOM on that console.

After a lot of debugging shenanigans, I found that sometimes, inside FRenderAssetInstanceAsyncView, the BoundsViewInfo for a certain component would return a component scale of -1.99839716e+18 which equates to 0xDDDDDDDD, i.e. the FMallocPoisonProxy freed data replacement. When the texel factor is eventually multiplied by this value, this in turn causes the texel factor to be interpreted as a literal size value, meaning it would always request the highest LOD. This disregards the expected behavior where objects are evaluated based on both their screen size and general visibility.

The reason for this I’m not 100% sure on, but I believe it’s a race condition when FCreateViewWithUninitializedBounds reallocates to a different uninitialized view (most likely it reuses a view that was previously released), but gets used before being able to properly reinitialize said view, possibly due to the incremental way this instance view gets filled.

While this on its own doesn’t do much, combined with FlushAsyncLoading, this causes textures to request their highest LODs all at once. Since FlushAsyncLoading seems to be called in many places inside the engine, I foresee this potentially happening during a fast-travel loading screen, and would like to have a workaround to prevent this spike from being an issue.

While I originally observed the issue on Xbox Series S, I’ve managed to reproduce this in a test project in Unreal Editor 5.6 as distributed on the Epic Games Launcher. This test project is currently attached, as well as the MemReports, the logs and the LLM CSV file generated during the run. The CSV creates a graph looking like below:

[Image Removed]

Any advice on fixing/working around this bug would be appreciated. At the very least it would help me avoid having to worry about the MemReport itself potentially skewing the memory results. Thanks!

Steps to Reproduce

  1. Create a set of high resolution textures (this can be done by creating one texture, then duplicating it in Unreal Editor)
  2. Assign each hi-res texture to a material, then each material to a cube in a level.
  3. Run the project with `-game` and `-llmcsv` commands.
  4. Spam the `memreport -full` command. Alternatively, you can spam the `listtextures` command.
  5. Check the generated LLM CSV file.
  6. Observe noticeable spikes.

Hi there,

Thanks for the reproduction project that really helps. I tried tracking down the issue, but unfortunately ended up in a similar situation to you, where I’m pretty sure there is a race condition, but can’t quite figure out where it is coming from. For now I’ve made a bug report, which will be publicly visible here once it has been triaged by Epic. The public bug report is quite short, as there is a character limit. However, I’ve attached very detailed notes with the report on Epic’s side. I note that, in my case I mainly get 0 for the ComponentScale and MaxNormalizedSize_VisibleOnly, but this triggers the same issue, though the code path may be a little more convoluted. It seems to me like the FRenderAssetInstanceAsyncView::Bounds4 array is populated with uninitialized bounds, which are not initialized before their use when the issue occurs. A subject matter expert should be able to fix this now that the bug has been reported. But, unfortunately I can’t give a timeframe for this, and I don’t have a good workaround currently. Once the bug report has been made public, you can vote on the issue to increase its priority.

I’ve attached my notes that I sent to Epic as an attachment to this thread. Let me know if there’s anything you would like to add.

Regards,

Lance Chaney