Summary
On macOS, EMetalFeaturesHeaps is set unconditionally (MetalDevice.cpp around line 348: the -metalheap / rhi.Metal.ForceNoHeap check is inside #if !PLATFORM_MAC), so every texture and buffer is sub-allocated from an FMetalResourceHeap. In MetalBuffer.cpp:
- METALHEAP_DEFAULT_BLOCKSIZE is a compile-time constant of 512 MB on Mac (line 1580; 128 MB on iOS, line 1583).
- FindOrAllocateBlock (line 1684) creates a new MTLHeap block when no free range fits.
- FreeBlock (line 1586) only returns ranges to the free list and merges neighbours. A block whose whole range is free again is never released.
No console variable, ini setting or command-line switch changes the block size or releases empty blocks on Mac (rhi.Metal.ResourcePurgeInPool and the texture pool apply only to the no-heap path; rhi.Metal.HeapBufferBytesToCompact is for buffers).
Engine: 5.8.3 launcher build (CL 58210709). Suggested fix: use a smaller block size on Mac (128 MB, as on iOS) or make it a console variable, and release a block’s MTLHeap in FreeBlock when its free list merges back into the whole block (keeping one spare block per resource-option list).
What Type of Bug are you experiencing?
Rendering (Graphics / Niagara)
Steps to Reproduce
- Package a project with a large streamed world for Mac.
- Fly or drive through the world so texture streaming loads and unloads a lot, then return to a quiet area.
- Compare
memreport -full(Metal heap stats) orfootprintbefore and after.
Expected Result
When streamed textures are unloaded, empty heap blocks go back to the OS (perhaps keeping one spare), so graphics memory follows actual use.
Observed Result
The graphics high-water mark only grows, in whole 512 MB steps, and varies run to run (4.40 / 4.91 / 5.43 GB peaks in the same test). Lowering r.Streaming.PoolSize does not reliably lower it. On a 16 GB M3 MacBook Air (macOS 26.6.2, UE 5.8.3 packaged Development build) the process peaks at 6.8-6.9 GB in a city fly-through.
Other developers report the same symptom: Apple Developer Forums thread Security Verification (January 2026, UE 5.4-5.7, “Metal heap blocks are never returned”); Apple’s engineers replied that their own Metal heap sample does not reproduce it and suggested reporting it to Epic.
Related Mac Metal memory reports: [Metal][Mac] FMetalDescriptorHeap destructor is empty: every FlushPendingDescriptorUpdates leaks an FRHIHeapDescriptorAllocator + FMetalRHIBuffer (steady memory growth on METAL_SM6) and [Metal][Mac] FMetalViewport::PresentDrawLayers retains LocalDrawable and never releases it: one CAMetalDrawable leaked per presented frame
Affects Versions
5.8
Platform(s)
Mac