Video: keep the VRAM heap cap at 2048

3072 was set to get the God of War 3 demo past an allocation failure, but that
failure was measured before the uninterruptible reclaim fix landed, and the cap is
not coordinated with the texture cache, which budgets itself up to 2560MB on
Android. Raising one without the other let the total grow with it: Batman: Arkham
City reached 5596MB resident against a 6246MB peak on a 7.2GB device and stalled
after a while, with no allocation failure to point at.

2048 is the value that shipped before, and it is where the sum of the two sat when
that game worked. Budgeting the cap and the cache together is the actual fix and
is not attempted here.
This commit is contained in:
jpolo1224
2026-08-11 15:10:41 -04:00
parent ae1caf915b
commit f056d6fc86
2 changed files with 15 additions and 10 deletions
@@ -87,10 +87,9 @@ object ConfigStore {
//
// Deliberately per-game and not a global default. It is off-spec, upstream defaults it
// on, and Sonic Unleashed fails EARLIER with it off, so it is not safe to apply blindly.
"BLUS30218" to mapOf("ps3AccurateSpuRsv" to false),
)
"BLUS30218" to mapOf("ps3AccurateSpuRsv" to false), )
// The VRAM limit is a hard heap cap, not an eviction threshold; too low fails allocations.
private const val KEY_VRAM_LIMIT_1024 = "config.migrated.vramCap3072"
private const val KEY_VRAM_LIMIT_1024 = "config.migrated.vramCap2048b"
private const val KEY_AFFINITY_ON = "config.migrated.affinityScheduler"
// ...and back off it: the mask it enables confines six SPU threads to four cores.
private const val KEY_AFFINITY_OS = "config.migrated.affinitySchedulerOff"
@@ -231,8 +230,8 @@ object ConfigStore {
// 1.6GB resident and 280MB in that pool, and failing at 2048 one screen later. A
// deliberate choice of some other value is left alone.
if (!MainActivityRuntime.prefs.getBoolean(KEY_VRAM_LIMIT_1024, false)) {
if (raw != null && (parsed.ps3.vramLimitMb == 2048 || parsed.ps3.vramLimitMb == 1024)) {
parsed = parsed.copy(ps3 = parsed.ps3.copy(vramLimitMb = 3072))
if (raw != null && (parsed.ps3.vramLimitMb == 1024 || parsed.ps3.vramLimitMb == 3072)) {
parsed = parsed.copy(ps3 = parsed.ps3.copy(vramLimitMb = 2048))
dirty = true
}
MainActivityRuntime.prefs.edit { putBoolean(KEY_VRAM_LIMIT_1024, true) }
@@ -158,12 +158,18 @@ data class Ps3Settings(
* held only 1.6GB resident and 280MB in that pool -- an artificial ceiling, not the hardware.
* At 2048 it failed too, one screen later.
*
* It still has to be finite. Upstream's 65536 means no cap at all, which suits a discrete
* card with its own memory; here the GPU shares system RAM, and an unbounded texture cache
* quota was previously measured driving the process to 4.3GB and getting it killed. 3072
* leaves the caches room to work while keeping that bound.
* Back to 2048, the value shipped before 0.5. 3072 was set to get the God of War 3 demo past
* an allocation failure, but that failure was measured BEFORE the uninterruptible reclaim
* fix landed, and raising the ceiling has its own cost: the texture cache budgets itself up
* to 2560MB on Android, so a higher cap lets the total grow with it. Batman: Arkham City was
* measured at 5596MB resident with a 6246MB peak on a 7.2GB device and stalled after a while
* -- no allocation failure, but far enough into memory pressure that the present pipeline
* collapses to a single frame in flight.
*
* The cap and the texture cache budget are not coordinated, which is the underlying problem;
* 2048 keeps their sum where it was when this game worked.
*/
val vramLimitMb: Int = 3072,
val vramLimitMb: Int = 2048,
val asyncTexStream: Boolean = false,
val audioFormat: Int = 0,
val audioChannels: Int = 0,