|
|
@@ -3,6 +3,7 @@ using Silk.NET.Vulkan;
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Diagnostics;
|
|
|
+using System.Threading;
|
|
|
|
|
|
namespace Ryujinx.Graphics.Vulkan
|
|
|
{
|
|
|
@@ -166,6 +167,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|
|
|
|
|
private readonly int _blockAlignment;
|
|
|
|
|
|
+ private readonly ReaderWriterLockSlim _lock;
|
|
|
+
|
|
|
public MemoryAllocatorBlockList(Vk api, Device device, int memoryTypeIndex, int blockAlignment, bool forBuffer)
|
|
|
{
|
|
|
_blocks = new List<Block>();
|
|
|
@@ -174,6 +177,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|
|
MemoryTypeIndex = memoryTypeIndex;
|
|
|
ForBuffer = forBuffer;
|
|
|
_blockAlignment = blockAlignment;
|
|
|
+ _lock = new(LockRecursionPolicy.NoRecursion);
|
|
|
}
|
|
|
|
|
|
public unsafe MemoryAllocation Allocate(ulong size, ulong alignment, bool map)
|
|
|
@@ -184,19 +188,28 @@ namespace Ryujinx.Graphics.Vulkan
|
|
|
throw new ArgumentOutOfRangeException(nameof(alignment), $"Invalid alignment 0x{alignment:X}.");
|
|
|
}
|
|
|
|
|
|
- for (int i = 0; i < _blocks.Count; i++)
|
|
|
- {
|
|
|
- var block = _blocks[i];
|
|
|
+ _lock.EnterReadLock();
|
|
|
|
|
|
- if (block.Mapped == map && block.Size >= size)
|
|
|
+ try
|
|
|
+ {
|
|
|
+ for (int i = 0; i < _blocks.Count; i++)
|
|
|
{
|
|
|
- ulong offset = block.Allocate(size, alignment);
|
|
|
- if (offset != InvalidOffset)
|
|
|
+ var block = _blocks[i];
|
|
|
+
|
|
|
+ if (block.Mapped == map && block.Size >= size)
|
|
|
{
|
|
|
- return new MemoryAllocation(this, block, block.Memory, GetHostPointer(block, offset), offset, size);
|
|
|
+ ulong offset = block.Allocate(size, alignment);
|
|
|
+ if (offset != InvalidOffset)
|
|
|
+ {
|
|
|
+ return new MemoryAllocation(this, block, block.Memory, GetHostPointer(block, offset), offset, size);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+ finally
|
|
|
+ {
|
|
|
+ _lock.ExitReadLock();
|
|
|
+ }
|
|
|
|
|
|
ulong blockAlignedSize = BitUtils.AlignUp(size, (ulong)_blockAlignment);
|
|
|
|
|
|
@@ -244,14 +257,23 @@ namespace Ryujinx.Graphics.Vulkan
|
|
|
|
|
|
if (block.IsTotallyFree())
|
|
|
{
|
|
|
- for (int i = 0; i < _blocks.Count; i++)
|
|
|
+ _lock.EnterWriteLock();
|
|
|
+
|
|
|
+ try
|
|
|
{
|
|
|
- if (_blocks[i] == block)
|
|
|
+ for (int i = 0; i < _blocks.Count; i++)
|
|
|
{
|
|
|
- _blocks.RemoveAt(i);
|
|
|
- break;
|
|
|
+ if (_blocks[i] == block)
|
|
|
+ {
|
|
|
+ _blocks.RemoveAt(i);
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
+ finally
|
|
|
+ {
|
|
|
+ _lock.ExitWriteLock();
|
|
|
+ }
|
|
|
|
|
|
block.Destroy(_api, _device);
|
|
|
}
|
|
|
@@ -259,13 +281,22 @@ namespace Ryujinx.Graphics.Vulkan
|
|
|
|
|
|
private void InsertBlock(Block block)
|
|
|
{
|
|
|
- int index = _blocks.BinarySearch(block);
|
|
|
- if (index < 0)
|
|
|
+ _lock.EnterWriteLock();
|
|
|
+
|
|
|
+ try
|
|
|
{
|
|
|
- index = ~index;
|
|
|
- }
|
|
|
+ int index = _blocks.BinarySearch(block);
|
|
|
+ if (index < 0)
|
|
|
+ {
|
|
|
+ index = ~index;
|
|
|
+ }
|
|
|
|
|
|
- _blocks.Insert(index, block);
|
|
|
+ _blocks.Insert(index, block);
|
|
|
+ }
|
|
|
+ finally
|
|
|
+ {
|
|
|
+ _lock.ExitWriteLock();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
public void Dispose()
|