Explorar o código

Convert MaxTextureCacheCapacity to Dynamic MaxTextureCacheCapacity for High Resolution Mod support. (#7307)

* Add Texture Size Capacity and 8GB Dram Build

* Update AutoDeleteCache.cs

* Dynamic Texture Cache (WIP)

* Change to float Multiplier, in-case it needs fine-tuning.

* Delete src/src.sln

* Update AutoDeleteCache.cs

* Format

* Fix Formatting

* Add DefaultTextureSizeCapacity and MemoryScaleFactor

- Also remove redundant New Lines

* Fix 4GB dram crashing

* Format newline

* Refractor

- Added Initialize() function to TextureCache and AutoDeleteCache
- Removed GetMaxTextureCapacity() function and instead added _maxCacheMemoryUsage
- Added private const MaxTextureSizeCapacity to AutoDelete Cache
- Added TextureCache.Initialize() to MemoryManager in order to fetch MaxGpuMemory at the right time.
- Moved and Changed Logger.Info for Gpu Memory to Logger.Notice and Moved it to PrintGpuInformation function.
- Opted to use a ternary operator for the Initialize function, I think it looks cleaner than bunch of if statements.

* Update src/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* maxMemory to CacheMemory, use Clamp instead of Ternary. Changed MinTextureCapacity 1GiB to 512 MiB

* Update src/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Format comment

* comment context

* Increase TextureSize capacity for OpenGL back to 1024

- Added a new const ulong for OpenGLTextureSizeCapacity

* Fix changes from last commit.

* Adjust last OpenGL changes.

* Remove garbage VSC file

* Update src/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Update src/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Update src/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

---------

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
MaxLastBreath hai 1 ano
pai
achega
d86249cb0a

+ 5 - 1
src/Ryujinx.Graphics.GAL/Capabilities.cs

@@ -71,6 +71,8 @@ namespace Ryujinx.Graphics.GAL
 
         public readonly int GatherBiasPrecision;
 
+        public readonly ulong MaximumGpuMemory;
+
         public Capabilities(
             TargetApi api,
             string vendorName,
@@ -131,7 +133,8 @@ namespace Ryujinx.Graphics.GAL
             int shaderSubgroupSize,
             int storageBufferOffsetAlignment,
             int textureBufferOffsetAlignment,
-            int gatherBiasPrecision)
+            int gatherBiasPrecision,
+            ulong maximumGpuMemory)
         {
             Api = api;
             VendorName = vendorName;
@@ -193,6 +196,7 @@ namespace Ryujinx.Graphics.GAL
             StorageBufferOffsetAlignment = storageBufferOffsetAlignment;
             TextureBufferOffsetAlignment = textureBufferOffsetAlignment;
             GatherBiasPrecision = gatherBiasPrecision;
+            MaximumGpuMemory = maximumGpuMemory;
         }
     }
 }

+ 27 - 3
src/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs

@@ -1,3 +1,4 @@
+using System;
 using System.Collections;
 using System.Collections.Generic;
 
@@ -46,7 +47,11 @@ namespace Ryujinx.Graphics.Gpu.Image
     {
         private const int MinCountForDeletion = 32;
         private const int MaxCapacity = 2048;
-        private const ulong MaxTextureSizeCapacity = 1024 * 1024 * 1024; // MB;
+        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 float MemoryScaleFactor = 0.50f;
+        private ulong _maxCacheMemoryUsage = 0;
 
         private readonly LinkedList<Texture> _textures;
         private ulong _totalSize;
@@ -56,6 +61,25 @@ namespace Ryujinx.Graphics.Gpu.Image
 
         private readonly Dictionary<TextureDescriptor, ShortTextureCacheEntry> _shortCacheLookup;
 
+        /// <summary>
+        /// Initializes the cache, setting the maximum texture capacity for the specified GPU context.
+        /// </summary>
+        /// <remarks>
+        /// If the backend GPU has 0 memory capacity, the cache size defaults to `DefaultTextureSizeCapacity`.
+        /// </remarks>
+        /// <param name="context">The GPU context that the cache belongs to</param>
+        public void Initialize(GpuContext context)
+        {
+            var cacheMemory = (ulong)(context.Capabilities.MaximumGpuMemory * MemoryScaleFactor);
+
+            _maxCacheMemoryUsage = Math.Clamp(cacheMemory, MinTextureSizeCapacity, MaxTextureSizeCapacity);
+
+            if (context.Capabilities.MaximumGpuMemory == 0)
+            {
+                _maxCacheMemoryUsage = DefaultTextureSizeCapacity;
+            }
+        }
+
         /// <summary>
         /// Creates a new instance of the automatic deletion cache.
         /// </summary>
@@ -85,7 +109,7 @@ namespace Ryujinx.Graphics.Gpu.Image
             texture.CacheNode = _textures.AddLast(texture);
 
             if (_textures.Count > MaxCapacity ||
-                (_totalSize > MaxTextureSizeCapacity && _textures.Count >= MinCountForDeletion))
+                (_totalSize > _maxCacheMemoryUsage && _textures.Count >= MinCountForDeletion))
             {
                 RemoveLeastUsedTexture();
             }
@@ -110,7 +134,7 @@ namespace Ryujinx.Graphics.Gpu.Image
                     _textures.AddLast(texture.CacheNode);
                 }
 
-                if (_totalSize > MaxTextureSizeCapacity && _textures.Count >= MinCountForDeletion)
+                if (_totalSize > _maxCacheMemoryUsage && _textures.Count >= MinCountForDeletion)
                 {
                     RemoveLeastUsedTexture();
                 }

+ 8 - 0
src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs

@@ -68,6 +68,14 @@ namespace Ryujinx.Graphics.Gpu.Image
             _cache = new AutoDeleteCache();
         }
 
+        /// <summary>
+        /// Initializes the cache, setting the maximum texture capacity for the specified GPU context.
+        /// </summary>
+        public void Initialize()
+        {
+            _cache.Initialize(_context);
+        }
+
         /// <summary>
         /// Handles marking of textures written to a memory region being (partially) remapped.
         /// </summary>

+ 2 - 0
src/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs

@@ -1,4 +1,5 @@
 using Ryujinx.Common.Memory;
+using Ryujinx.Graphics.Gpu.Image;
 using Ryujinx.Memory;
 using Ryujinx.Memory.Range;
 using System;
@@ -64,6 +65,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
             MemoryUnmapped += Physical.BufferCache.MemoryUnmappedHandler;
             MemoryUnmapped += VirtualRangeCache.MemoryUnmappedHandler;
             MemoryUnmapped += CounterCache.MemoryUnmappedHandler;
+            Physical.TextureCache.Initialize();
         }
 
         /// <summary>

+ 2 - 1
src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs

@@ -202,7 +202,8 @@ namespace Ryujinx.Graphics.OpenGL
                 shaderSubgroupSize: Constants.MaxSubgroupSize,
                 storageBufferOffsetAlignment: HwCapabilities.StorageBufferOffsetAlignment,
                 textureBufferOffsetAlignment: HwCapabilities.TextureBufferOffsetAlignment,
-                gatherBiasPrecision: intelWindows || amdWindows ? 8 : 0); // Precision is 8 for these vendors on Vulkan.
+                gatherBiasPrecision: intelWindows || amdWindows ? 8 : 0, // Precision is 8 for these vendors on Vulkan.
+                maximumGpuMemory: 0);
         }
 
         public void SetBufferData(BufferHandle buffer, int offset, ReadOnlySpan<byte> data)

+ 21 - 1
src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs

@@ -781,7 +781,26 @@ namespace Ryujinx.Graphics.Vulkan
                 shaderSubgroupSize: (int)Capabilities.SubgroupSize,
                 storageBufferOffsetAlignment: (int)limits.MinStorageBufferOffsetAlignment,
                 textureBufferOffsetAlignment: (int)limits.MinTexelBufferOffsetAlignment,
-                gatherBiasPrecision: IsIntelWindows || IsAmdWindows ? (int)Capabilities.SubTexelPrecisionBits : 0);
+                gatherBiasPrecision: IsIntelWindows || IsAmdWindows ? (int)Capabilities.SubTexelPrecisionBits : 0,
+                maximumGpuMemory: GetTotalGPUMemory());
+        }
+
+        private ulong GetTotalGPUMemory()
+        {
+            ulong totalMemory = 0;
+
+            Api.GetPhysicalDeviceMemoryProperties(_physicalDevice.PhysicalDevice, out PhysicalDeviceMemoryProperties memoryProperties);
+
+            for (int i = 0; i < memoryProperties.MemoryHeapCount; i++)
+            {
+                var heap = memoryProperties.MemoryHeaps[i];
+                if ((heap.Flags & MemoryHeapFlags.DeviceLocalBit) == MemoryHeapFlags.DeviceLocalBit)
+                {
+                    totalMemory += heap.Size;
+                }
+            }
+
+            return totalMemory;
         }
 
         public HardwareInfo GetHardwareInfo()
@@ -865,6 +884,7 @@ namespace Ryujinx.Graphics.Vulkan
         private void PrintGpuInformation()
         {
             Logger.Notice.Print(LogClass.Gpu, $"{GpuVendor} {GpuRenderer} ({GpuVersion})");
+            Logger.Notice.Print(LogClass.Gpu, $"GPU Memory: {GetTotalGPUMemory() / (1024 * 1024)} MiB");
         }
 
         public void Initialize(GraphicsDebugLevel logLevel)