diff options
| author | gdk <gab.dark.100@gmail.com> | 2019-11-24 21:29:37 -0300 |
|---|---|---|
| committer | Thog <thog@protonmail.com> | 2020-01-09 02:13:00 +0100 |
| commit | d0c7732fe21bc5c234ac611759e51926d2c8947e (patch) | |
| tree | ebc47b31dff5c03a1f0125ba4809e373968f08ec /Ryujinx.Graphics.Gpu/Memory | |
| parent | e0c95b18eb225d62301b8e3c3fe9d4f689381100 (diff) | |
Optimize RangeList by not doing an allocation on every call to the Find methods
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Memory')
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Memory/BufferManager.cs | 31 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Memory/RangeList.cs | 52 |
2 files changed, 61 insertions, 22 deletions
diff --git a/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs b/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs index 30bd1302..a066585c 100644 --- a/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs +++ b/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs @@ -8,6 +8,9 @@ namespace Ryujinx.Graphics.Gpu.Memory { class BufferManager { + private const int OverlapsBufferInitialCapacity = 10; + private const int OverlapsBufferMaxCapacity = 10000; + private const ulong BufferAlignmentSize = 0x1000; private const ulong BufferAlignmentMask = BufferAlignmentSize - 1; @@ -15,6 +18,8 @@ namespace Ryujinx.Graphics.Gpu.Memory private RangeList<Buffer> _buffers; + private Buffer[] _bufferOverlaps; + private IndexBuffer _indexBuffer; private VertexBuffer[] _vertexBuffers; @@ -57,6 +62,8 @@ namespace Ryujinx.Graphics.Gpu.Memory _buffers = new RangeList<Buffer>(); + _bufferOverlaps = new Buffer[OverlapsBufferInitialCapacity]; + _vertexBuffers = new VertexBuffer[Constants.TotalVertexBuffers]; _cpStorageBuffers = new BuffersPerStage(Constants.TotalCpStorageBuffers); @@ -207,9 +214,9 @@ namespace Ryujinx.Graphics.Gpu.Memory private void CreateBuffer(ulong address, ulong size) { - Buffer[] overlaps = _buffers.FindOverlapsNonOverlapping(address, size); + int overlapsCount = _buffers.FindOverlapsNonOverlapping(address, size, ref _bufferOverlaps); - if (overlaps.Length != 0) + if (overlapsCount != 0) { // The buffer already exists. We can just return the existing buffer // if the buffer we need is fully contained inside the overlapping buffer. @@ -218,10 +225,12 @@ namespace Ryujinx.Graphics.Gpu.Memory // old buffer(s) to the new buffer. ulong endAddress = address + size; - if (overlaps[0].Address > address || overlaps[0].EndAddress < endAddress) + if (_bufferOverlaps[0].Address > address || _bufferOverlaps[0].EndAddress < endAddress) { - foreach (Buffer buffer in overlaps) + for (int index = 0; index < overlapsCount; index++) { + Buffer buffer = _bufferOverlaps[index]; + address = Math.Min(address, buffer.Address); endAddress = Math.Max(endAddress, buffer.EndAddress); @@ -234,8 +243,10 @@ namespace Ryujinx.Graphics.Gpu.Memory _buffers.Add(newBuffer); - foreach (Buffer buffer in overlaps) + for (int index = 0; index < overlapsCount; index++) { + Buffer buffer = _bufferOverlaps[index]; + int dstOffset = (int)(buffer.Address - newBuffer.Address); buffer.CopyTo(newBuffer, dstOffset); @@ -253,6 +264,16 @@ namespace Ryujinx.Graphics.Gpu.Memory _buffers.Add(buffer); } + + ShrinkOverlapsBufferIfNeeded(); + } + + private void ShrinkOverlapsBufferIfNeeded() + { + if (_bufferOverlaps.Length > OverlapsBufferMaxCapacity) + { + Array.Resize(ref _bufferOverlaps, OverlapsBufferMaxCapacity); + } } public ulong GetComputeUniformBufferAddress(int index) diff --git a/Ryujinx.Graphics.Gpu/Memory/RangeList.cs b/Ryujinx.Graphics.Gpu/Memory/RangeList.cs index e3435292..45f23cf3 100644 --- a/Ryujinx.Graphics.Gpu/Memory/RangeList.cs +++ b/Ryujinx.Graphics.Gpu/Memory/RangeList.cs @@ -1,9 +1,12 @@ +using System; using System.Collections.Generic; namespace Ryujinx.Graphics.Gpu.Memory { class RangeList<T> where T : IRange<T> { + private const int ArrayGrowthSize = 32; + private List<T> _items; public RangeList() @@ -72,14 +75,14 @@ namespace Ryujinx.Graphics.Gpu.Memory return _items[index]; } - public T[] FindOverlaps(T item) + public int FindOverlaps(T item, ref T[] output) { - return FindOverlaps(item.Address, item.Size); + return FindOverlaps(item.Address, item.Size, ref output); } - public T[] FindOverlaps(ulong address, ulong size) + public int FindOverlaps(ulong address, ulong size, ref T[] output) { - List<T> overlapsList = new List<T>(); + int outputIndex = 0; ulong endAddress = address + size; @@ -94,24 +97,29 @@ namespace Ryujinx.Graphics.Gpu.Memory if (item.OverlapsWith(address, size)) { - overlapsList.Add(item); + if (outputIndex == output.Length) + { + Array.Resize(ref output, outputIndex + ArrayGrowthSize); + } + + output[outputIndex++] = item; } } } - return overlapsList.ToArray(); + return outputIndex; } - public T[] FindOverlapsNonOverlapping(T item) + public int FindOverlapsNonOverlapping(T item, ref T[] output) { - return FindOverlapsNonOverlapping(item.Address, item.Size); + return FindOverlapsNonOverlapping(item.Address, item.Size, ref output); } - public T[] FindOverlapsNonOverlapping(ulong address, ulong size) + public int FindOverlapsNonOverlapping(ulong address, ulong size, ref T[] output) { // This is a bit faster than FindOverlaps, but only works // when none of the items on the list overlaps with each other. - List<T> overlapsList = new List<T>(); + int outputIndex = 0; ulong endAddress = address + size; @@ -126,20 +134,25 @@ namespace Ryujinx.Graphics.Gpu.Memory do { - overlapsList.Add(_items[index++]); + if (outputIndex == output.Length) + { + Array.Resize(ref output, outputIndex + ArrayGrowthSize); + } + + output[outputIndex++] = _items[index++]; } while (index < _items.Count && _items[index].OverlapsWith(address, size)); } - return overlapsList.ToArray(); + return outputIndex; } - public T[] FindOverlaps(ulong address) + public int FindOverlaps(ulong address, ref T[] output) { - List<T> overlapsList = new List<T>(); - int index = BinarySearch(address); + int outputIndex = 0; + if (index >= 0) { while (index > 0 && _items[index - 1].Address == address) @@ -156,11 +169,16 @@ namespace Ryujinx.Graphics.Gpu.Memory break; } - overlapsList.Add(overlap); + if (outputIndex == output.Length) + { + Array.Resize(ref output, outputIndex + ArrayGrowthSize); + } + + output[outputIndex++] = overlap; } } - return overlapsList.ToArray(); + return outputIndex; } private int BinarySearch(ulong address) |
