From fb27042e01b0fa110184673d436ec96ec8cf20c7 Mon Sep 17 00:00:00 2001 From: gdkchan 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 /// public const int TotalTransformFeedbackBuffers = 4; - /// - /// Maximum number of textures on a single shader stage. - /// - /// - /// The maximum number of textures is API limited, the hardware supports an unlimited amount. - /// - public const int TotalTextures = 32; - - /// - /// Maximum number of images on a single shader stage. - /// - /// - /// The maximum number of images is API limited, the hardware supports an unlimited amount. - /// - public const int TotalImages = 8; - /// /// Maximum number of render target color buffers. /// @@ -100,5 +84,15 @@ namespace Ryujinx.Graphics.Gpu /// Expected byte alignment for storage buffers /// public const int StorageAlignment = 16; + + /// + /// Number of the uniform buffer reserved by the driver to store the storage buffer base addresses. + /// + public const int DriverReservedUniformBuffer = 0; + + /// + /// Maximum size that an storage buffer is assumed to have when the correct size is unknown. + /// + 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(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 _state; @@ -359,7 +357,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed SbDescriptor sbDescriptor = _channel.MemoryManager.Physical.Read(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(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; }