diff --git a/src/Ryujinx.Graphics.Gpu/GpuContext.cs b/src/Ryujinx.Graphics.Gpu/GpuContext.cs index 048d32fb7..fb529e914 100644 --- a/src/Ryujinx.Graphics.Gpu/GpuContext.cs +++ b/src/Ryujinx.Graphics.Gpu/GpuContext.cs @@ -152,16 +152,17 @@ namespace Ryujinx.Graphics.Gpu /// 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 ad6c1fecb..74967b190 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 @@ namespace Ryujinx.Graphics.Gpu.Image { 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 @@ namespace Ryujinx.Graphics.Gpu.Image /// /// /// 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 cpuMemorySizeGiB = cpuMemorySize / GiB; + + 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); - if (context.Capabilities.MaximumGpuMemory == 0) - { - _maxCacheMemoryUsage = DefaultTextureSizeCapacity; - } + 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 1587e2018..2cfd9af5b 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs @@ -71,9 +71,10 @@ namespace Ryujinx.Graphics.Gpu.Image /// /// 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 d1065431d..59e618c02 100644 --- a/src/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs +++ b/src/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs @@ -55,7 +55,8 @@ namespace Ryujinx.Graphics.Gpu.Memory /// 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 @@ namespace Ryujinx.Graphics.Gpu.Memory 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 ff9a67644..0f5d7547c 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 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu 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(); }