From f94acdb4efcf48555481f38417f8befa4ca560ad Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sun, 24 Jan 2021 19:22:19 -0300 Subject: [PATCH] Allow out of bounds storage buffer access by aligning their sizes (#1870) * Allow out of bounds storage buffer access by aligning their sizes * Use correct size * Fix typo and comment on the reason for the change --- Ryujinx.Graphics.Gpu/Memory/Buffer.cs | 15 +++++++++++++ Ryujinx.Graphics.Gpu/Memory/BufferManager.cs | 23 ++++++++++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/Ryujinx.Graphics.Gpu/Memory/Buffer.cs b/Ryujinx.Graphics.Gpu/Memory/Buffer.cs index 7127871a7..cdd61b6d9 100644 --- a/Ryujinx.Graphics.Gpu/Memory/Buffer.cs +++ b/Ryujinx.Graphics.Gpu/Memory/Buffer.cs @@ -88,6 +88,21 @@ namespace Ryujinx.Graphics.Gpu.Memory _modifiedDelegate = new Action(RegionModified); } + /// + /// Gets a sub-range from the buffer, from a start address till the end of the buffer. + /// + /// + /// This can be used to bind and use sub-ranges of the buffer on the host API. + /// + /// Start address of the sub-range, must be greater than or equal to the buffer address + /// The buffer sub-range + public BufferRange GetRange(ulong address) + { + ulong offset = address - Address; + + return new BufferRange(Handle, (int)offset, (int)(Size - offset)); + } + /// /// Gets a sub-range from the buffer. /// diff --git a/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs b/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs index cdcc5a370..08d52faa4 100644 --- a/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs +++ b/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs @@ -591,7 +591,12 @@ namespace Ryujinx.Graphics.Gpu.Memory if (bounds.Address != 0) { - sRanges[bindingInfo.Binding] = GetBufferRange(bounds.Address, bounds.Size, bounds.Flags.HasFlag(BufferUsageFlags.Write)); + // The storage buffer size is not reliable (it might be lower than the actual size), + // so we bind the entire buffer to allow otherwise out of range accesses to work. + sRanges[bindingInfo.Binding] = GetBufferRangeTillEnd( + bounds.Address, + bounds.Size, + bounds.Flags.HasFlag(BufferUsageFlags.Write)); } } @@ -764,7 +769,9 @@ namespace Ryujinx.Graphics.Gpu.Memory if (bounds.Address != 0) { - ranges[bindingInfo.Binding] = GetBufferRange(bounds.Address, bounds.Size, bounds.Flags.HasFlag(BufferUsageFlags.Write)); + ranges[bindingInfo.Binding] = isStorage + ? GetBufferRangeTillEnd(bounds.Address, bounds.Size, bounds.Flags.HasFlag(BufferUsageFlags.Write)) + : GetBufferRange(bounds.Address, bounds.Size, bounds.Flags.HasFlag(BufferUsageFlags.Write)); } } } @@ -895,6 +902,18 @@ namespace Ryujinx.Graphics.Gpu.Memory buffer.SignalModified(address, size); } + /// + /// Gets a buffer sub-range starting at a given memory address. + /// + /// Start address of the memory range + /// Size in bytes of the memory range + /// Whether the buffer will be written to by this use + /// The buffer sub-range starting at the given memory address + private BufferRange GetBufferRangeTillEnd(ulong address, ulong size, bool write = false) + { + return GetBuffer(address, size, write).GetRange(address); + } + /// /// Gets a buffer sub-range for a given memory range. ///