See merge request ryubing/ryujinx!132
This commit is contained in:
LotP
2025-08-30 20:30:17 -05:00
parent 6e47d8548c
commit 01a9b636af
7 changed files with 161 additions and 84 deletions

View File

@@ -81,16 +81,8 @@ namespace Ryujinx.Graphics.Device
if (index < Size)
{
uint alignedOffset = index * RegisterSize;
Func<int> readCallback = Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(_readCallbacks), (nint)index);
if (readCallback != null)
{
return readCallback();
}
else
{
return GetRefUnchecked<int>(alignedOffset);
}
return _readCallbacks[index]?.Invoke() ?? GetRefUnchecked<int>(alignedOffset);
}
return 0;
@@ -107,7 +99,7 @@ namespace Ryujinx.Graphics.Device
GetRefIntAlignedUncheck(index) = data;
Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(_writeCallbacks), (nint)index)?.Invoke(data);
_writeCallbacks[index]?.Invoke(data);
}
}
@@ -124,7 +116,7 @@ namespace Ryujinx.Graphics.Device
changed = storage != data;
storage = data;
Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(_writeCallbacks), (nint)index)?.Invoke(data);
_writeCallbacks[index]?.Invoke(data);
}
else
{

View File

@@ -109,7 +109,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
if (index < BlockSize)
{
int groupIndex = Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(_registerToGroupMapping), (nint)index);
int groupIndex = _registerToGroupMapping[index];
if (groupIndex != 0)
{
groupIndex--;

View File

@@ -120,11 +120,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
public void ExcludeModifiedRegions(ulong address, ulong size, Action<ulong, ulong> action)
{
// Slices a given region using the modified regions in the list. Calls the action for the new slices.
bool lockOwner = Lock.IsReadLockHeld;
if (!lockOwner)
{
Lock.EnterReadLock();
}
Lock.EnterReadLock();
(RangeItem<BufferModifiedRange> first, RangeItem<BufferModifiedRange> last) = FindOverlaps(address, size);
@@ -145,10 +141,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
current = current.Next;
}
if (!lockOwner)
{
Lock.ExitReadLock();
}
Lock.ExitReadLock();
if ((long)size > 0)
{
@@ -179,9 +172,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
return;
}
BufferModifiedRange buffPost = null;
bool extendsPost = false;
bool extendsPre = false;
if (first == last)
{
@@ -196,14 +187,12 @@ namespace Ryujinx.Graphics.Gpu.Memory
if (first.Address < address)
{
first.Value.Size = address - first.Address;
extendsPre = true;
Update(first);
if (first.EndAddress > endAddress)
{
buffPost = new BufferModifiedRange(endAddress, first.EndAddress - endAddress,
first.Value.SyncNumber, first.Value.Parent);
extendsPost = true;
Add(new BufferModifiedRange(endAddress, first.EndAddress - endAddress,
first.Value.SyncNumber, first.Value.Parent));
}
}
else
@@ -212,6 +201,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
{
first.Value.Size = first.EndAddress - endAddress;
first.Value.Address = endAddress;
Update(first);
}
else
{
@@ -219,11 +209,6 @@ namespace Ryujinx.Graphics.Gpu.Memory
}
}
if (extendsPre && extendsPost)
{
Add(buffPost);
}
Add(new BufferModifiedRange(address, size, syncNumber, this));
Lock.ExitWriteLock();
@@ -231,6 +216,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
}
BufferModifiedRange buffPre = null;
BufferModifiedRange buffPost = null;
bool extendsPost = false;
bool extendsPre = false;
if (first.Address < address)
{
@@ -329,7 +317,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
public bool HasRange(ulong address, ulong size)
{
Lock.EnterReadLock();
(RangeItem<BufferModifiedRange> first, RangeItem<BufferModifiedRange> _) = FindOverlaps(address, size);
RangeItem<BufferModifiedRange> first = FindOverlapFast(address, size);
bool result = first is not null;
Lock.ExitReadLock();
return result;
@@ -386,9 +374,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
ulong clampAddress = Math.Max(address, overlap.Address);
ulong clampEnd = Math.Min(endAddress, overlap.EndAddress);
Lock.EnterWriteLock();
ClearPart(overlap, clampAddress, clampEnd);
Lock.ExitWriteLock();
RangeActionWithMigration(clampAddress, clampEnd - clampAddress, waitSync, _flushAction);
}
@@ -418,40 +404,33 @@ namespace Ryujinx.Graphics.Gpu.Memory
ulong endAddress = address + size;
ulong currentSync = _context.SyncNumber;
int rangeCount = 0;
List<RangeItem<BufferModifiedRange>> overlaps = [];
// Range list must be consistent for this operation
Lock.EnterReadLock();
if (_migrationTarget != null)
{
rangeCount = -1;
}
else
{
// We use the non-span method here because the array is partially modified by the code, which would invalidate a span.
(RangeItem<BufferModifiedRange> first, RangeItem<BufferModifiedRange> last) = FindOverlaps(address, size);
RangeItem<BufferModifiedRange> current = first;
while (last != null && current != last.Next)
{
rangeCount++;
overlaps.Add(current);
current = current.Next;
}
}
Lock.ExitReadLock();
if (rangeCount == -1)
{
_migrationTarget!.WaitForAndFlushRanges(address, size);
return;
}
Lock.EnterWriteLock();
// We use the non-span method here because the array is partially modified by the code, which would invalidate a span.
(RangeItem<BufferModifiedRange> first, RangeItem<BufferModifiedRange> last) = FindOverlaps(address, size);
RangeItem<BufferModifiedRange> current = first;
while (last != null && current != last.Next)
{
overlaps.Add(current);
current = current.Next;
}
int rangeCount = overlaps.Count;
if (rangeCount == 0)
{
Lock.ExitWriteLock();
return;
}
@@ -474,6 +453,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
if (highestDiff == long.MinValue)
{
Lock.ExitWriteLock();
return;
}
@@ -481,6 +462,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
_context.Renderer.WaitSync(currentSync + (ulong)highestDiff);
RemoveRangesAndFlush(overlaps.ToArray(), rangeCount, highestDiff, currentSync, address, endAddress);
Lock.ExitWriteLock();
}
/// <summary>
@@ -607,22 +590,17 @@ namespace Ryujinx.Graphics.Gpu.Memory
return;
}
BufferModifiedRange buffPost = null;
bool extendsPost = false;
bool extendsPre = false;
if (first == last)
{
if (first.Address < address)
{
first.Value.Size = address - first.Address;
extendsPre = true;
Update(first);
if (first.EndAddress > endAddress)
{
buffPost = new BufferModifiedRange(endAddress, first.EndAddress - endAddress,
first.Value.SyncNumber, first.Value.Parent);
extendsPost = true;
Add(new BufferModifiedRange(endAddress, first.EndAddress - endAddress,
first.Value.SyncNumber, first.Value.Parent));
}
}
else
@@ -631,6 +609,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
{
first.Value.Size = first.EndAddress - endAddress;
first.Value.Address = endAddress;
Update(first);
}
else
{
@@ -638,16 +617,14 @@ namespace Ryujinx.Graphics.Gpu.Memory
}
}
if (extendsPre && extendsPost)
{
Add(buffPost);
}
Lock.ExitWriteLock();
return;
}
BufferModifiedRange buffPre = null;
BufferModifiedRange buffPost = null;
bool extendsPost = false;
bool extendsPre = false;
if (first.Address < address)
{

View File

@@ -87,6 +87,43 @@ namespace Ryujinx.Memory.Range
return false;
}
/// <summary>
/// Updates an item's end address on the list. Address must be the same.
/// </summary>
/// <param name="item">The RangeItem to be updated</param>
/// <returns>True if the item was located and updated, false otherwise</returns>
protected override bool Update(RangeItem<T> item)
{
int index = BinarySearch(item.Address);
RangeItem<T> rangeItem = new(item.Value) { Previous = item.Previous, Next = item.Next };
if (index > 0)
{
Items[index - 1].Next = rangeItem;
}
if (index < Count - 1)
{
Items[index + 1].Previous = rangeItem;
}
foreach (ulong addr in item.QuickAccessAddresses)
{
_quickAccess.Remove(addr);
_fastQuickAccess.Remove(addr);
}
Items[index] = rangeItem;
if (item.Address != rangeItem.Address)
_quickAccess.Remove(item.Address);
_quickAccess[rangeItem.Address] = rangeItem;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void Insert(int index, RangeItem<T> item)
{
@@ -193,10 +230,9 @@ namespace Ryujinx.Memory.Range
return;
}
int startIndex = BinarySearch(startItem.Address);
int endIndex = BinarySearch(endItem.Address);
(int startIndex, int endIndex) = BinarySearchEdges(startItem.Address, endItem.EndAddress);
for (int i = startIndex; i <= endIndex; i++)
for (int i = startIndex; i < endIndex; i++)
{
_quickAccess.Remove(Items[i].Address);
foreach (ulong addr in Items[i].QuickAccessAddresses)
@@ -206,23 +242,23 @@ namespace Ryujinx.Memory.Range
}
}
if (endIndex < Count - 1)
if (endIndex < Count)
{
Items[endIndex + 1].Previous = startIndex > 0 ? Items[startIndex - 1] : null;
Items[endIndex].Previous = startIndex > 0 ? Items[startIndex - 1] : null;
}
if (startIndex > 0)
{
Items[startIndex - 1].Next = endIndex < Count - 1 ? Items[endIndex + 1] : null;
Items[startIndex - 1].Next = endIndex < Count ? Items[endIndex] : null;
}
if (endIndex < Count - 1)
if (endIndex < Count)
{
Array.Copy(Items, endIndex + 1, Items, startIndex, Count - endIndex - 1);
Array.Copy(Items, endIndex, Items, startIndex, Count - endIndex);
}
Count -= endIndex - startIndex + 1;
Count -= endIndex - startIndex;
}
/// <summary>

View File

@@ -81,12 +81,73 @@ namespace Ryujinx.Memory.Range
{
if (Items[index].Value.Equals(item))
{
RangeItem<T> rangeItem = new(item) { Previous = Items[index].Previous, Next = Items[index].Next };
if (index > 0)
{
Items[index - 1].Next = rangeItem;
}
if (index < Count - 1)
{
Items[index + 1].Previous = rangeItem;
}
foreach (ulong address in Items[index].QuickAccessAddresses)
{
_quickAccess.Remove(address);
}
Items[index] = new RangeItem<T>(item);
Items[index] = rangeItem;
return true;
}
if (Items[index].Address > item.Address)
{
break;
}
index++;
}
}
return false;
}
/// <summary>
/// Updates an item's end address on the list. Address must be the same.
/// </summary>
/// <param name="item">The RangeItem to be updated</param>
/// <returns>True if the item was located and updated, false otherwise</returns>
protected override bool Update(RangeItem<T> item)
{
int index = BinarySearch(item.Address);
if (index >= 0)
{
while (index < Count)
{
if (Items[index].Equals(item))
{
RangeItem<T> rangeItem = new(item.Value) { Previous = item.Previous, Next = item.Next };
if (index > 0)
{
Items[index - 1].Next = rangeItem;
}
if (index < Count - 1)
{
Items[index + 1].Previous = rangeItem;
}
foreach (ulong address in item.QuickAccessAddresses)
{
_quickAccess.Remove(address);
}
Items[index] = rangeItem;
return true;
}

View File

@@ -30,7 +30,7 @@ namespace Ryujinx.Memory.Range
return u1 == u2;
}
public int GetHashCode(ulong value) => (int)(value >> 5);
public int GetHashCode(ulong value) => (int)(value << 5);
public static readonly AddressEqualityComparer Comparer = new();
}
@@ -63,6 +63,13 @@ namespace Ryujinx.Memory.Range
/// <returns>True if the item was located and updated, false otherwise</returns>
protected abstract bool Update(T item);
/// <summary>
/// Updates an item's end address on the list. Address must be the same.
/// </summary>
/// <param name="item">The RangeItem to be updated</param>
/// <returns>True if the item was located and updated, false otherwise</returns>
protected abstract bool Update(RangeItem<T> item);
public abstract bool Remove(T item);
public abstract void RemoveRange(RangeItem<T> startItem, RangeItem<T> endItem);

View File

@@ -182,11 +182,15 @@ namespace Ryujinx.Memory.Tracking
{
if (region.Guest)
{
_guestVirtualRegions.Lock.EnterWriteLock();
_guestVirtualRegions.Remove(region);
_guestVirtualRegions.Lock.ExitWriteLock();
}
else
{
_virtualRegions.Lock.EnterWriteLock();
_virtualRegions.Remove(region);
_virtualRegions.Lock.ExitWriteLock();
}
}