diff --git a/src/Ryujinx.Graphics.Gpu/GpuContext.cs b/src/Ryujinx.Graphics.Gpu/GpuContext.cs index 048d32fb79..fb529e914f 100644 --- a/src/Ryujinx.Graphics.Gpu/GpuContext.cs +++ b/src/Ryujinx.Graphics.Gpu/GpuContext.cs @@ -152,16 +152,17 @@ public GpuChannel CreateChannel() /// Creates a new GPU memory manager. /// /// ID of the process that owns the memory manager + /// The amount of physical CPU Memory Avaiable on the device. /// The memory manager /// Thrown when is invalid - public MemoryManager CreateMemoryManager(ulong pid) + public MemoryManager CreateMemoryManager(ulong pid, ulong cpuMemorySize) { if (!PhysicalMemoryRegistry.TryGetValue(pid, out var physicalMemory)) { throw new ArgumentException("The PID is invalid or the process was not registered", nameof(pid)); } - return new MemoryManager(physicalMemory); + return new MemoryManager(physicalMemory, cpuMemorySize); } /// diff --git a/src/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs b/src/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs index ad6c1fecb2..74967b1906 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs @@ -1,3 +1,4 @@ +using Ryujinx.Common.Logging; using System; using System.Collections; using System.Collections.Generic; @@ -47,11 +48,17 @@ class AutoDeleteCache : IEnumerable { private const int MinCountForDeletion = 32; private const int MaxCapacity = 2048; + private const ulong GiB = 1024 * 1024 * 1024; + private ulong MaxTextureSizeCapacity = 4UL * GiB; private const ulong MinTextureSizeCapacity = 512 * 1024 * 1024; - private const ulong MaxTextureSizeCapacity = 4UL * 1024 * 1024 * 1024; - private const ulong DefaultTextureSizeCapacity = 1UL * 1024 * 1024 * 1024; + private const ulong DefaultTextureSizeCapacity = 1 * GiB; + private const ulong TextureSizeCapacity6GiB = 4 * GiB; + private const ulong TextureSizeCapacity8GiB = 6 * GiB; + private const ulong TextureSizeCapacity12GiB = 12 * GiB; + + private const float MemoryScaleFactor = 0.50f; - private ulong _maxCacheMemoryUsage = 0; + private ulong _maxCacheMemoryUsage = DefaultTextureSizeCapacity; private readonly LinkedList _textures; private ulong _totalSize; @@ -66,18 +73,38 @@ class AutoDeleteCache : IEnumerable /// /// /// If the backend GPU has 0 memory capacity, the cache size defaults to `DefaultTextureSizeCapacity`. + /// + /// Reads the current Device total CPU Memory, to determine the maximum amount of Vram available. Capped to 50% of Current GPU Memory. /// /// The GPU context that the cache belongs to - public void Initialize(GpuContext context) + /// The amount of physical CPU Memory Avaiable on the device. + public void Initialize(GpuContext context, ulong cpuMemorySize) { - var cacheMemory = (ulong)(context.Capabilities.MaximumGpuMemory * MemoryScaleFactor); - - _maxCacheMemoryUsage = Math.Clamp(cacheMemory, MinTextureSizeCapacity, MaxTextureSizeCapacity); + var cpuMemorySizeGiB = cpuMemorySize / GiB; - if (context.Capabilities.MaximumGpuMemory == 0) + if (cpuMemorySizeGiB < 6 || context.Capabilities.MaximumGpuMemory == 0) { _maxCacheMemoryUsage = DefaultTextureSizeCapacity; + return; + } + else if (cpuMemorySizeGiB == 6) + { + MaxTextureSizeCapacity = TextureSizeCapacity6GiB; + } + else if (cpuMemorySizeGiB == 8) + { + MaxTextureSizeCapacity = TextureSizeCapacity8GiB; } + else + { + MaxTextureSizeCapacity = TextureSizeCapacity12GiB; + } + + var cacheMemory = (ulong)(context.Capabilities.MaximumGpuMemory * MemoryScaleFactor); + + _maxCacheMemoryUsage = Math.Clamp(cacheMemory, MinTextureSizeCapacity, MaxTextureSizeCapacity); + + Logger.Info?.Print(LogClass.Gpu, $"AutoDelete Cache Allocated VRAM : {_maxCacheMemoryUsage / GiB} GiB"); } /// diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs index 1587e20189..2cfd9af5b2 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs @@ -71,9 +71,10 @@ public TextureCache(GpuContext context, PhysicalMemory physicalMemory) /// /// Initializes the cache, setting the maximum texture capacity for the specified GPU context. /// - public void Initialize() + /// The amount of physical CPU Memory Avaiable on the device. + public void Initialize(ulong cpuMemorySize) { - _cache.Initialize(_context); + _cache.Initialize(_context, cpuMemorySize); } /// diff --git a/src/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs b/src/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs index d1065431d1..59e618c02d 100644 --- a/src/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs +++ b/src/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs @@ -55,7 +55,8 @@ public class MemoryManager : IWritableBlock /// Creates a new instance of the GPU memory manager. /// /// Physical memory that this memory manager will map into - internal MemoryManager(PhysicalMemory physicalMemory) + /// The amount of physical CPU Memory Avaiable on the device. + internal MemoryManager(PhysicalMemory physicalMemory, ulong cpuMemorySize) { Physical = physicalMemory; VirtualRangeCache = new VirtualRangeCache(this); @@ -65,7 +66,7 @@ internal MemoryManager(PhysicalMemory physicalMemory) MemoryUnmapped += Physical.BufferCache.MemoryUnmappedHandler; MemoryUnmapped += VirtualRangeCache.MemoryUnmappedHandler; MemoryUnmapped += CounterCache.MemoryUnmappedHandler; - Physical.TextureCache.Initialize(); + Physical.TextureCache.Initialize(cpuMemorySize); } /// diff --git a/src/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/NvHostAsGpuDeviceFile.cs b/src/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/NvHostAsGpuDeviceFile.cs index ff9a676449..0f5d7547cc 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/NvHostAsGpuDeviceFile.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nv/NvDrvServices/NvHostAsGpu/NvHostAsGpuDeviceFile.cs @@ -42,7 +42,7 @@ public VmRegion(ulong start, ulong limit) public NvHostAsGpuDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, ulong owner) : base(context, owner) { - _asContext = new AddressSpaceContext(context.Device.Gpu.CreateMemoryManager(owner)); + _asContext = new AddressSpaceContext(context.Device.Gpu.CreateMemoryManager(owner, context.Device.Memory.Size)); _memoryAllocator = new NvMemoryAllocator(); }