diff options
Diffstat (limited to 'Ryujinx.Memory.Tests')
| -rw-r--r-- | Ryujinx.Memory.Tests/MockVirtualMemoryManager.cs | 2 | ||||
| -rw-r--r-- | Ryujinx.Memory.Tests/MultiRegionTrackingTests.cs | 36 | ||||
| -rw-r--r-- | Ryujinx.Memory.Tests/TrackingTests.cs | 56 |
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. + } } } |
