diff --git a/Source/Core/Common/MemoryUtil.cpp b/Source/Core/Common/MemoryUtil.cpp index db60a475ed..36de6b23a0 100644 --- a/Source/Core/Common/MemoryUtil.cpp +++ b/Source/Core/Common/MemoryUtil.cpp @@ -19,6 +19,12 @@ #else #include #include +#include +#ifdef __APPLE__ +#include +#else +#include +#endif #endif // Valgrind doesn't support MAP_32BIT. @@ -241,3 +247,26 @@ std::string MemUsage() return ""; #endif } + + +size_t MemPhysical() +{ +#ifdef _WIN32 + MEMORYSTATUSEX memInfo; + memInfo.dwLength = sizeof(MEMORYSTATUSEX); + GlobalMemoryStatusEx(&memInfo); + return memInfo.ullTotalPhys; +#elif defined(__APPLE__) + int mib[2]; + size_t physical_memory; + mib[0] = CTL_HW; + mib[1] = HW_MEMSIZE; + size_t length = sizeof(size_t); + sysctl(mib, 2, &physical_memory, &length, NULL, 0); + return physical_memory; +#else + struct sysinfo memInfo; + sysinfo (&memInfo); + return (size_t)memInfo.totalram * memInfo.mem_unit; +#endif +} diff --git a/Source/Core/Common/MemoryUtil.h b/Source/Core/Common/MemoryUtil.h index 5f584f868d..49a55756c0 100644 --- a/Source/Core/Common/MemoryUtil.h +++ b/Source/Core/Common/MemoryUtil.h @@ -16,6 +16,7 @@ void ReadProtectMemory(void* ptr, size_t size); void WriteProtectMemory(void* ptr, size_t size, bool executable = false); void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute = false); std::string MemUsage(); +size_t MemPhysical(); void GuardMemoryMake(void* ptr, size_t size); void GuardMemoryUnmake(void* ptr, size_t size); diff --git a/Source/Core/VideoCommon/HiresTextures.cpp b/Source/Core/VideoCommon/HiresTextures.cpp index d29bde1b12..3e163f34ee 100644 --- a/Source/Core/VideoCommon/HiresTextures.cpp +++ b/Source/Core/VideoCommon/HiresTextures.cpp @@ -16,6 +16,7 @@ #include "Common/FileSearch.h" #include "Common/FileUtil.h" #include "Common/Flag.h" +#include "Common/MemoryUtil.h" #include "Common/StringUtil.h" #include "Common/Thread.h" #include "Common/Timer.h" @@ -167,6 +168,7 @@ void HiresTexture::Prefetch() Common::SetCurrentThreadName("Prefetcher"); size_t size_sum = 0; + size_t max_mem = MemPhysical() / 2; u32 starttime = Common::Timer::GetTimeMs(); for (const auto& entry : s_textureMap) { @@ -203,6 +205,14 @@ void HiresTexture::Prefetch() { return; } + + if (size_sum > max_mem) + { + g_Config.bCacheHiresTextures = false; + + OSD::AddMessage(StringFromFormat("Custom Textures prefetching after %.1f MB aborted, not enough RAM available", size_sum / (1024.0 * 1024.0)), 10000); + return; + } } u32 stoptime = Common::Timer::GetTimeMs(); OSD::AddMessage(StringFromFormat("Custom Textures loaded, %.1f MB in %.1f s", size_sum / (1024.0 * 1024.0), (stoptime - starttime) / 1000.0), 10000);