From fb27042e01b0fa110184673d436ec96ec8cf20c7 Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
Date: Sat, 20 May 2023 13:15:07 -0300
Subject: [PATCH] Limit compute storage buffer size (#5028)

---
 src/Ryujinx.Graphics.Gpu/Constants.cs         | 26 +++++++------------
 .../Engine/Compute/ComputeClass.cs            | 14 +++++++++-
 .../Engine/Threed/StateUpdater.cs             |  6 ++---
 src/Ryujinx.Graphics.Vulkan/BufferManager.cs  | 18 ++++++++++---
 4 files changed, 40 insertions(+), 24 deletions(-)

diff --git a/src/Ryujinx.Graphics.Gpu/Constants.cs b/src/Ryujinx.Graphics.Gpu/Constants.cs
index 1897f5d0fa..b559edc25b 100644
--- a/src/Ryujinx.Graphics.Gpu/Constants.cs
+++ b/src/Ryujinx.Graphics.Gpu/Constants.cs
@@ -40,22 +40,6 @@ namespace Ryujinx.Graphics.Gpu
         /// </summary>
         public const int TotalTransformFeedbackBuffers = 4;
 
-        /// <summary>
-        /// Maximum number of textures on a single shader stage.
-        /// </summary>
-        /// <remarks>
-        /// The maximum number of textures is API limited, the hardware supports an unlimited amount.
-        /// </remarks>
-        public const int TotalTextures = 32;
-
-        /// <summary>
-        /// Maximum number of images on a single shader stage.
-        /// </summary>
-        /// <remarks>
-        /// The maximum number of images is API limited, the hardware supports an unlimited amount.
-        /// </remarks>
-        public const int TotalImages = 8;
-
         /// <summary>
         /// Maximum number of render target color buffers.
         /// </summary>
@@ -100,5 +84,15 @@ namespace Ryujinx.Graphics.Gpu
         /// Expected byte alignment for storage buffers
         /// </summary>
         public const int StorageAlignment = 16;
+
+        /// <summary>
+        /// Number of the uniform buffer reserved by the driver to store the storage buffer base addresses.
+        /// </summary>
+        public const int DriverReservedUniformBuffer = 0;
+
+        /// <summary>
+        /// Maximum size that an storage buffer is assumed to have when the correct size is unknown.
+        /// </summary>
+        public const ulong MaxUnknownStorageSize = 0x100000;
     }
 }
\ No newline at end of file
diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Compute/ComputeClass.cs b/src/Ryujinx.Graphics.Gpu/Engine/Compute/ComputeClass.cs
index 4ec23c7911..998ece2247 100644
--- a/src/Ryujinx.Graphics.Gpu/Engine/Compute/ComputeClass.cs
+++ b/src/Ryujinx.Graphics.Gpu/Engine/Compute/ComputeClass.cs
@@ -162,7 +162,19 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
 
                 SbDescriptor sbDescriptor = _channel.MemoryManager.Physical.Read<SbDescriptor>(sbDescAddress);
 
-                _channel.BufferManager.SetComputeStorageBuffer(sb.Slot, sbDescriptor.PackAddress(), (uint)sbDescriptor.Size, sb.Flags);
+                uint size;
+                if (sb.SbCbSlot == Constants.DriverReservedUniformBuffer)
+                {
+                    // Only trust the SbDescriptor size if it comes from slot 0.
+                    size = (uint)sbDescriptor.Size;
+                }
+                else
+                {
+                    // TODO: Use full mapped size and somehow speed up buffer sync.
+                    size = (uint)_channel.MemoryManager.GetMappedSize(sbDescriptor.PackAddress(), Constants.MaxUnknownStorageSize);
+                }
+
+                _channel.BufferManager.SetComputeStorageBuffer(sb.Slot, sbDescriptor.PackAddress(), size, sb.Flags);
             }
 
             if ((_channel.BufferManager.HasUnalignedStorageBuffers) != hasUnaligned)
diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs
index 87e58ead78..4feb8bafc6 100644
--- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs
+++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs
@@ -23,8 +23,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
         public const int PrimitiveRestartStateIndex = 12;
         public const int RenderTargetStateIndex = 27;
 
-        private const ulong MaxUnknownStorageSize = 0x100000;
-
         private readonly GpuContext _context;
         private readonly GpuChannel _channel;
         private readonly DeviceStateWithShadow<ThreedClassState> _state;
@@ -359,7 +357,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
                     SbDescriptor sbDescriptor = _channel.MemoryManager.Physical.Read<SbDescriptor>(sbDescAddress);
 
                     uint size;
-                    if (sb.SbCbSlot == 0)
+                    if (sb.SbCbSlot == Constants.DriverReservedUniformBuffer)
                     {
                         // Only trust the SbDescriptor size if it comes from slot 0.
                         size = (uint)sbDescriptor.Size;
@@ -367,7 +365,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
                     else
                     {
                         // TODO: Use full mapped size and somehow speed up buffer sync.
-                        size = (uint)_channel.MemoryManager.GetMappedSize(sbDescriptor.PackAddress(), MaxUnknownStorageSize);
+                        size = (uint)_channel.MemoryManager.GetMappedSize(sbDescriptor.PackAddress(), Constants.MaxUnknownStorageSize);
                     }
 
                     _channel.BufferManager.SetGraphicsStorageBuffer(stage, sb.Slot, sbDescriptor.PackAddress(), size, sb.Flags);
diff --git a/src/Ryujinx.Graphics.Vulkan/BufferManager.cs b/src/Ryujinx.Graphics.Vulkan/BufferManager.cs
index 27678ed5ed..e046bf8992 100644
--- a/src/Ryujinx.Graphics.Vulkan/BufferManager.cs
+++ b/src/Ryujinx.Graphics.Vulkan/BufferManager.cs
@@ -1,4 +1,5 @@
-using Ryujinx.Graphics.GAL;
+using Ryujinx.Common.Logging;
+using Ryujinx.Graphics.GAL;
 using Silk.NET.Vulkan;
 using System;
 using System.Runtime.CompilerServices;
@@ -95,16 +96,27 @@ namespace Ryujinx.Graphics.Vulkan
             return Unsafe.As<ulong, BufferHandle>(ref handle64);
         }
 
-        public BufferHandle CreateWithHandle(VulkanRenderer gd, int size, BufferAllocationType baseType = BufferAllocationType.HostMapped, BufferHandle storageHint = default)
+        public BufferHandle CreateWithHandle(
+            VulkanRenderer gd,
+            int size,
+            BufferAllocationType baseType = BufferAllocationType.HostMapped,
+            BufferHandle storageHint = default)
         {
             return CreateWithHandle(gd, size, out _, baseType, storageHint);
         }
 
-        public BufferHandle CreateWithHandle(VulkanRenderer gd, int size, out BufferHolder holder, BufferAllocationType baseType = BufferAllocationType.HostMapped, BufferHandle storageHint = default)
+        public BufferHandle CreateWithHandle(
+            VulkanRenderer gd,
+            int size,
+            out BufferHolder holder,
+            BufferAllocationType baseType = BufferAllocationType.HostMapped,
+            BufferHandle storageHint = default)
         {
             holder = Create(gd, size, baseType: baseType, storageHint: storageHint);
             if (holder == null)
             {
+                Logger.Error?.Print(LogClass.Gpu, $"Failed to create buffer with size 0x{size:X} and type \"{baseType}\".");
+
                 return BufferHandle.Null;
             }