libretro: size the Quake hunk from frontend-reported free memory

The hunk was a fixed compile-time size (DEFAULT_MEMSIZE_MB, 8/24/32/64 MB
depending on platform and whether the Vulkan RHI is built). That is a
blunt instrument: too small and large mods hit Hunk_Alloc failures or
thrash Cache_FreeLow; too large and constrained targets over-commit.

Add an experimental environment callback, RETRO_ENVIRONMENT_GET_MEMORY_STATUS,
that reports the frontend's free and total physical memory (bytes), and use
it to size the hunk to the running machine. We take at most a quarter of the
reported free memory, cap it at 256 MB (ample for the biggest Quake mods,
and lazily committed so the reservation is cheap on virtual-memory
platforms), and only ever grow above the per-platform default - never below
it. The value is treated as an advisory snapshot, not a licence to allocate
everything, since "free" can include reclaimable cache.

Frontends that do not implement the query return false; in that case the
core keeps the exact defaults it uses today, so behaviour is unchanged
anywhere the callback is absent. The matching frontend side is a separate
RetroArch change wiring the call to frontend_driver_get_free_memory().
This commit is contained in:
libretroadmin authored and libretroadmin committed 2026-07-01 06:44:59 +02:00
1 parent ff36964795
commit 8f1e7dcdcd
2 files changed
+66

No files matched your search

+36
View File
@@ -134,6 +134,16 @@ static bool libretro_supports_bitmasks = false;
#define DEFAULT_MEMSIZE_MB 64
#endif
/* Bounds for frontend-driven hunk sizing via
* RETRO_ENVIRONMENT_GET_MEMORY_STATUS: take at most 1/4 of the memory the
* frontend reports free, cap it, and never shrink below the per-platform
* DEFAULT_MEMSIZE_MB chosen above. The cap keeps the reservation sane on
* desktops with gigabytes free while still covering the largest mods; the
* floor preserves the current tuned behaviour on constrained targets and
* on any frontend that cannot answer the query. */
#define HUNK_FREE_SHIFT 2 /* free >> 2 == a quarter of reported free RAM */
#define HUNK_MAX_MB 256u /* upper bound; ample for the biggest Quake mods */
/* Use 44.1 kHz by default (matches CD
* audio tracks) */
#define AUDIO_SAMPLERATE_DEFAULT 44100
@@ -1321,6 +1331,32 @@ bool retro_load_game(const struct retro_game_info *info)
parms.basedir = g_rom_dir;
parms.savedir = g_save_dir;
parms.use_exernal_savedir = use_external_savedir ? 1 : 0;
/* Size the Quake hunk from the memory the frontend actually has, when it
* can tell us. We only ever grow above the default and clamp hard, so a
* frontend that does not implement the query (returns false) keeps the
* compile-time default computed above. */
{
struct retro_memory_status memstat;
memstat.free = memstat.total = 0;
if (environ_cb(RETRO_ENVIRONMENT_GET_MEMORY_STATUS, &memstat) && memstat.free)
{
unsigned free_mb = (unsigned)(memstat.free / (1024 * 1024));
unsigned budget = free_mb >> HUNK_FREE_SHIFT;
if (budget > HUNK_MAX_MB)
budget = HUNK_MAX_MB;
if (budget > MEMSIZE_MB)
MEMSIZE_MB = budget;
log_cb(RETRO_LOG_INFO,
"Frontend reports %u MB free; sizing Quake hunk to %u MB.\n",
free_mb, MEMSIZE_MB);
}
else
log_cb(RETRO_LOG_INFO,
"Frontend has no memory-status query; using default %u MB hunk.\n",
MEMSIZE_MB);
}
parms.memsize = MEMSIZE_MB * 1024 * 1024;
argv[0] = empty_string;
+30
View File
@@ -2643,6 +2643,36 @@ enum retro_mod
*/
#define RETRO_ENVIRONMENT_GET_AUDIO_SAMPLE_BATCH_FLOAT (85 | RETRO_ENVIRONMENT_EXPERIMENTAL)
/**
* Queries how much system memory the frontend has available.
*
* A core may use this to size large internal allocations (a memory pool,
* heap or asset cache) to the running machine instead of to a fixed
* compile-time default. The reported values are advisory snapshots: \c free
* in particular may include reclaimable cache and can change immediately
* after the call, so a core should take a fraction of it and clamp the
* result -- it must never assume it can allocate the whole amount.
*
* Frontends that do not implement this return \c false, in which case the
* core is expected to fall back to its own defaults.
*
* @param[out] data <tt>struct retro_memory_status *</tt>.
* @return \c true if the frontend filled in the structure, \c false otherwise.
* @see retro_memory_status
*/
#define RETRO_ENVIRONMENT_GET_MEMORY_STATUS (86 | RETRO_ENVIRONMENT_EXPERIMENTAL)
/**
* Result of \c RETRO_ENVIRONMENT_GET_MEMORY_STATUS.
*
* Sizes are in bytes; a field the frontend cannot determine is left at 0.
*/
struct retro_memory_status
{
uint64_t free; /**< Physical memory currently available to allocate. */
uint64_t total; /**< Total physical memory installed. */
};
/**@}*/
/**