Groom LOD data remains fully resident in VRAM regardless of distance / LOD level

We’re working on a multiplayer action RPG with up to 50 MetaHuman NPCs active simultaneously. All groom assets are set to use cards only (no strand rendering), yet we’re seeing approximately 800 MB of total VRAM consumption from grooms — roughly 400 MB in asset data and another 400 MB in runtime Hair buffers (deformed positions, root triangles, guide buffers — around 5,366 buffer entries total across all characters).

The core issue is that groom VRAM allocations appear to be fully resident at all times. Unlike Nanite cluster pages or texture streaming, there doesn’t seem to be any mechanism to evict groom LOD data that isn’t currently in use. Moving far away from NPCs doesn’t reduce the memory footprint at all.

We’re running on an RTX 3070 (8 GB) and this single system accounts for nearly 25% of our tracked VRAM budget, which is pushing us into overflow.

A few specific questions:

  1. Is there any existing or planned support for groom memory streaming, similar to how Nanite or the texture streaming coordinator manages residency based on visibility and distance?
  2. Given that we’re exclusively using cards and not rendering strands, are the guide and strand-related runtime buffers (Hair.StrandsRootDeformed, etc.) still expected to be allocated? It seems like these shouldn’t be necessary in a cards-only configuration.
  3. Is there a recommended approach for managing groom memory at scale with many MetaHumans? We’re currently considering a pooling system that destroys/creates groom components based on distance, but we’d appreciate guidance on whether there’s a more engine-native solution we’re missing.

Any insight into the intended workflow for this scenario would be very helpful.

From RHI.DumpResourceMemory:

Buffers with owner “None” 400 MB:

[Image Removed]

Textures and Buffers with owner that contains “groom” 400 MB:

[Image Removed]

[Attachment Removed]

Hi,

Thanks for sharing these details. Here are some brief answer to your questions.

> Is there any existing or planned support for groom memory streaming, similar to how Nanite or the texture streaming coordinator manages residency based on visibility and distance?

There is no plan for cards to have streaming pool at this time. The current system expects that if a groom card is no longer needed, it should no longer be referenced by active instances, and both groom component and groom asset will be collected by the garbage collector.

> Given that we’re exclusively using cards and not rendering strands, are the guide and strand-related runtime buffers (Hair.StrandsRootDeformed, etc.) still expected to be allocated? It seems like these shouldn’t be necessary in a cards-only configuration.

  • Guides data will be allocated and used if you enable either hair simulation or RBF interpolation.
  • Root data will be allocated and used if ‘skinning’ is used as binding method for any LOD (configured under the LOD panel within the groom editor). If you use ‘rigid’ instead, these root resources shouldn’t be allocated/used.

> Is there a recommended approach for managing groom memory at scale with many MetaHumans? We’re currently considering a pooling system that destroys/creates groom components based on distance, but we’d appreciate guidance on whether there’s a more engine-native solution we’re missing.

There is no existing code dedicated for crowd usage. We are working on this at the moment, but there is no ETA at this stage.

Let me know if you need further details.

/Charles.

[Attachment Removed]