aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Memory.Tests
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Memory.Tests')
-rw-r--r--Ryujinx.Memory.Tests/MockVirtualMemoryManager.cs2
-rw-r--r--Ryujinx.Memory.Tests/MultiRegionTrackingTests.cs36
-rw-r--r--Ryujinx.Memory.Tests/TrackingTests.cs56
3 files changed, 93 insertions, 1 deletions
diff --git a/Ryujinx.Memory.Tests/MockVirtualMemoryManager.cs b/Ryujinx.Memory.Tests/MockVirtualMemoryManager.cs
index 938c9d1d..05e157b6 100644
--- a/Ryujinx.Memory.Tests/MockVirtualMemoryManager.cs
+++ b/Ryujinx.Memory.Tests/MockVirtualMemoryManager.cs
@@ -79,7 +79,7 @@ namespace Ryujinx.Memory.Tests
throw new NotImplementedException();
}
- public void SignalMemoryTracking(ulong va, ulong size, bool write)
+ public void SignalMemoryTracking(ulong va, ulong size, bool write, bool precise = false)
{
throw new NotImplementedException();
}
diff --git a/Ryujinx.Memory.Tests/MultiRegionTrackingTests.cs b/Ryujinx.Memory.Tests/MultiRegionTrackingTests.cs
index 05756503..c607464d 100644
--- a/Ryujinx.Memory.Tests/MultiRegionTrackingTests.cs
+++ b/Ryujinx.Memory.Tests/MultiRegionTrackingTests.cs
@@ -399,5 +399,41 @@ namespace Ryujinx.Memory.Tests
Assert.AreEqual(singlePages[1], combinedHandles.ElementAt(9));
Assert.AreEqual(singlePages[2], combinedHandles.ElementAt(10));
}
+
+ [Test]
+ public void PreciseAction()
+ {
+ bool actionTriggered = false;
+
+ MultiRegionHandle granular = _tracking.BeginGranularTracking(PageSize * 3, PageSize * 3, null, PageSize);
+ PreparePages(granular, 3, PageSize * 3);
+
+ // Add a precise action to the second and third handle in the multiregion.
+ granular.RegisterPreciseAction(PageSize * 4, PageSize * 2, (_, _, _) => { actionTriggered = true; return true; });
+
+ // Precise write to first handle in the multiregion.
+ _tracking.VirtualMemoryEvent(PageSize * 3, PageSize, true, precise: true);
+ Assert.IsFalse(actionTriggered); // Action not triggered.
+
+ bool firstPageModified = false;
+ granular.QueryModified(PageSize * 3, PageSize, (_, _) => { firstPageModified = true; });
+ Assert.IsTrue(firstPageModified); // First page is modified.
+
+ // Precise write to all handles in the multiregion.
+ _tracking.VirtualMemoryEvent(PageSize * 3, PageSize * 3, true, precise: true);
+
+ bool[] pagesModified = new bool[3];
+
+ for (int i = 3; i < 6; i++)
+ {
+ int index = i - 3;
+ granular.QueryModified(PageSize * (ulong)i, PageSize, (_, _) => { pagesModified[index] = true; });
+ }
+
+ Assert.IsTrue(actionTriggered); // Action triggered.
+
+ // Precise writes are ignored on two later handles due to the action returning true.
+ Assert.AreEqual(pagesModified, new bool[] { true, false, false });
+ }
}
}
diff --git a/Ryujinx.Memory.Tests/TrackingTests.cs b/Ryujinx.Memory.Tests/TrackingTests.cs
index 8f0612a1..d273ace3 100644
--- a/Ryujinx.Memory.Tests/TrackingTests.cs
+++ b/Ryujinx.Memory.Tests/TrackingTests.cs
@@ -449,5 +449,61 @@ namespace Ryujinx.Memory.Tests
handle.Dispose();
}
+
+ [Test]
+ public void PreciseAction()
+ {
+ RegionHandle handle = _tracking.BeginTracking(0, PageSize);
+
+ (ulong address, ulong size, bool write)? preciseTriggered = null;
+ handle.RegisterPreciseAction((address, size, write) =>
+ {
+ preciseTriggered = (address, size, write);
+
+ return true;
+ });
+
+ (ulong address, ulong size)? readTrackingTriggered = null;
+ handle.RegisterAction((address, size) =>
+ {
+ readTrackingTriggered = (address, size);
+ });
+
+ handle.Reprotect();
+
+ _tracking.VirtualMemoryEvent(0, 4, false, precise: true);
+
+ Assert.IsNull(readTrackingTriggered); // Hasn't been triggered - precise action returned true.
+ Assert.AreEqual(preciseTriggered, (0UL, 4UL, false)); // Precise action was triggered.
+
+ _tracking.VirtualMemoryEvent(0, 4, true, precise: true);
+
+ Assert.IsNull(readTrackingTriggered); // Still hasn't been triggered.
+ bool dirtyAfterPreciseActionTrue = handle.Dirty;
+ Assert.False(dirtyAfterPreciseActionTrue); // Not dirtied - precise action returned true.
+ Assert.AreEqual(preciseTriggered, (0UL, 4UL, true)); // Precise action was triggered.
+
+ // Handle is now dirty.
+ handle.Reprotect(true);
+ preciseTriggered = null;
+
+ _tracking.VirtualMemoryEvent(4, 4, true, precise: true);
+ Assert.AreEqual(preciseTriggered, (4UL, 4UL, true)); // Precise action was triggered even though handle was dirty.
+
+ handle.Reprotect();
+ handle.RegisterPreciseAction((address, size, write) =>
+ {
+ preciseTriggered = (address, size, write);
+
+ return false; // Now, we return false, which indicates that the regular read/write behaviours should trigger.
+ });
+
+ _tracking.VirtualMemoryEvent(8, 4, true, precise: true);
+
+ Assert.AreEqual(readTrackingTriggered, (8UL, 4UL)); // Read action triggered, as precise action returned false.
+ bool dirtyAfterPreciseActionFalse = handle.Dirty;
+ Assert.True(dirtyAfterPreciseActionFalse); // Dirtied, as precise action returned false.
+ Assert.AreEqual(preciseTriggered, (8UL, 4UL, true)); // Precise action was triggered.
+ }
}
}