Home Products Contracting Purchase Resellers About Contact
Home Products Contracting Purchase Resellers About Blog Contact
VMem VMem

Integrating VMem into Unreal Engine 4.18

Copy these files to Engine\Source\Runtime\Core\Public\HAL\

VMem\VMemSingleFile\VMem.cpp
VMem\VMemSingleFile\VMem.h
VMem\EngineIntegration\Unreal4\MallocVMem.cpp
VMem\EngineIntegration\Unreal4\MallocVMem.h

In this file add VMem to the EMemoryAllocatorToUse enum

Engine\Source\Runtime\Core\Public\GenericPlatform\GenericPlatformMemory.h

/** Which allocator is being used */
enum EMemoryAllocatorToUse
{
    Ansi, // Default C allocator
    Stomp, // Allocator to check for memory stomping
    TBB, // Thread Building Blocks malloc
    Jemalloc, // Linux/FreeBSD malloc
    Binned, // Older binned malloc
    Binned2, // Newer binned malloc
    VMem, // VMem
    Platform, // Custom platform specific allocator
};

In this file add VMem to the switch statement:

Engine\Source\Runtime\Core\Private\Windows\WindowsPlatformMemory.cpp

// Set rather to use BinnedMalloc2 for binned malloc, can be overridden below
#define USE_MALLOC_BINNED2 (0)
#define USE_MALLOC_VMEM (1)

FMalloc* FWindowsPlatformMemory::BaseAllocator()
{
    #if ENABLE_WIN_ALLOC_TRACKING
        // This allows tracking of allocations that don't happen within the engine's wrappers.
        // This actually won't be compiled unless bDebugBuildsActuallyUseDebugCRT is set in the
        // build configuration for UBT.
        _CrtSetAllocHook(WindowsAllocHook);
    #endif // ENABLE_WIN_ALLOC_TRACKING
    
        if (FORCE_ANSI_ALLOCATOR) //-V517
        {
            AllocatorToUse = EMemoryAllocatorToUse::Ansi;
        }
        else if (USE_MALLOC_STOMP)
        {
            AllocatorToUse = EMemoryAllocatorToUse::Stomp;
        }
        else if (USE_MALLOC_VMEM)
        {
            AllocatorToUse = EMemoryAllocatorToUse::VMem;
        }

        else if ((WITH_EDITORONLY_DATA || IS_PROGRAM) && TBB_ALLOCATOR_ALLOWED)
        {
            AllocatorToUse = EMemoryAllocatorToUse::TBB;
        }
        else if (USE_MALLOC_BINNED2)
        {
            AllocatorToUse = EMemoryAllocatorToUse::Binned2;
        }
        else
        {
            AllocatorToUse = EMemoryAllocatorToUse::Binned;
        }
    
    #if !UE_BUILD_SHIPPING
        // If not shipping, allow overriding with command line options, this happens very early so we need to use windows functions
        const TCHAR* CommandLine = ::GetCommandLineW();
    
        if (FCString::Stristr(CommandLine, TEXT("-ansimalloc")))
        {
            AllocatorToUse = EMemoryAllocatorToUse::Ansi;
        }
        else if (FCString::Stristr(CommandLine, TEXT("-tbbmalloc")))
        {
            AllocatorToUse = EMemoryAllocatorToUse::TBB;
        }
        else if (FCString::Stristr(CommandLine, TEXT("-binnedmalloc2")))
        {
            AllocatorToUse = EMemoryAllocatorToUse::Binned2;
        }
        else if (FCString::Stristr(CommandLine, TEXT("-binnedmalloc")))
        {
            AllocatorToUse = EMemoryAllocatorToUse::Binned;
        }
        else if (FCString::Stristr(CommandLine, TEXT("-vmemmalloc")))
        {
            AllocatorToUse = EMemoryAllocatorToUse::VMem;
        }

    #endif
    
        switch (AllocatorToUse)
        {
        case EMemoryAllocatorToUse::Ansi:
            return new FMallocAnsi();
    #if USE_MALLOC_STOMP
        case EMemoryAllocatorToUse::Stomp:
            return new FMallocStomp();
    #endif
        case EMemoryAllocatorToUse::TBB:
            return new FMallocTBB();
        case EMemoryAllocatorToUse::Binned2:
            return new FMallocBinned2();
        case EMemoryAllocatorToUse::VMem:
                 return new FMallocVMem();

        
        default: // intentional fall-through
        case EMemoryAllocatorToUse::Binned:
            return new FMallocBinned((uint32)(GetConstants().BinnedPageSize&MAX_uint32), (uint64)MAX_uint32 + 1);
        }
}