diff options
| author | riperiperi <rhy3756547@hotmail.com> | 2021-01-17 20:08:06 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-01-17 17:08:06 -0300 |
| commit | a1f77a5b6ab33bbcc0a8e070e50cee24ad82eac1 (patch) | |
| tree | 9faccd644a7eac3f33ad5e66db87c947dab972ed /Ryujinx.Memory/Tracking | |
| parent | c4f56c570494a6186792439e3c0e74458cc82b5c (diff) | |
Implement lazy flush-on-read for Buffers (SSBO/Copy) (#1790)
* Initial implementation of buffer flush (VERY WIP)
* Host shaders need to be rebuilt for the SSBO write flag.
* New approach with reserved regions and gl sync
* Fix a ton of buffer issues.
* Remove unused buffer unmapped behaviour
* Revert "Remove unused buffer unmapped behaviour"
This reverts commit f1700e52fb8760180ac5e0987a07d409d1e70ece.
* Delete modified ranges on unmap
Fixes potential crashes in Super Smash Bros, where a previously modified range could lie on either side of an unmap.
* Cache some more delegates.
* Dispose Sync on Close
* Also create host sync for GPFifo syncpoint increment.
* Copy buffer optimization, add docs
* Fix race condition with OpenGL Sync
* Enable read tracking on CommandBuffer, insert syncpoint on WaitForIdle
* Performance: Only flush individual pages of SSBO at a time
This avoids flushing large amounts of data when only a small amount is actually used.
* Signal Modified rather than flushing after clear
* Fix some docs and code style.
* Introduce a new test for tracking memory protection.
Sucessfully demonstrates that the bug causing write protection to be cleared by a read action has been fixed. (these tests fail on master)
* Address Comments
* Add host sync for SetReference
This ensures that any indirect draws will correctly flush any related buffer data written before them. Fixes some flashing and misplaced world geometry in MH rise.
* Make PageAlign static
* Re-enable read tracking, for reads.
Diffstat (limited to 'Ryujinx.Memory/Tracking')
| -rw-r--r-- | Ryujinx.Memory/Tracking/MultiRegionHandle.cs | 11 | ||||
| -rw-r--r-- | Ryujinx.Memory/Tracking/RegionHandle.cs | 1 | ||||
| -rw-r--r-- | Ryujinx.Memory/Tracking/SmartMultiRegionHandle.cs | 20 | ||||
| -rw-r--r-- | Ryujinx.Memory/Tracking/VirtualRegion.cs | 4 |
4 files changed, 34 insertions, 2 deletions
diff --git a/Ryujinx.Memory/Tracking/MultiRegionHandle.cs b/Ryujinx.Memory/Tracking/MultiRegionHandle.cs index 02ae3a8b..df154bc2 100644 --- a/Ryujinx.Memory/Tracking/MultiRegionHandle.cs +++ b/Ryujinx.Memory/Tracking/MultiRegionHandle.cs @@ -123,6 +123,17 @@ namespace Ryujinx.Memory.Tracking } } + public void RegisterAction(ulong address, ulong size, RegionSignal action) + { + int startHandle = (int)((address - Address) / Granularity); + int lastHandle = (int)((address + (size - 1) - Address) / Granularity); + + for (int i = startHandle; i <= lastHandle; i++) + { + _handles[i].RegisterAction(action); + } + } + public void Dispose() { foreach (var handle in _handles) diff --git a/Ryujinx.Memory/Tracking/RegionHandle.cs b/Ryujinx.Memory/Tracking/RegionHandle.cs index 96898c21..3ddcb6db 100644 --- a/Ryujinx.Memory/Tracking/RegionHandle.cs +++ b/Ryujinx.Memory/Tracking/RegionHandle.cs @@ -24,6 +24,7 @@ namespace Ryujinx.Memory.Tracking private readonly MemoryTracking _tracking; internal MemoryPermission RequiredPermission => _preAction != null ? MemoryPermission.None : (Dirty ? MemoryPermission.ReadAndWrite : MemoryPermission.Read); + internal RegionSignal PreAction => _preAction; /// <summary> /// Create a new region handle. The handle is registered with the given tracking object, diff --git a/Ryujinx.Memory/Tracking/SmartMultiRegionHandle.cs b/Ryujinx.Memory/Tracking/SmartMultiRegionHandle.cs index 60188400..8bc10c41 100644 --- a/Ryujinx.Memory/Tracking/SmartMultiRegionHandle.cs +++ b/Ryujinx.Memory/Tracking/SmartMultiRegionHandle.cs @@ -41,6 +41,17 @@ namespace Ryujinx.Memory.Tracking Dirty = true; } + public void RegisterAction(RegionSignal action) + { + foreach (var handle in _handles) + { + if (handle != null) + { + handle?.RegisterAction((address, size) => action(handle.Address, handle.Size)); + } + } + } + public void QueryModified(Action<ulong, ulong> modifiedAction) { if (!Dirty) @@ -66,14 +77,23 @@ namespace Ryujinx.Memory.Tracking ulong size = HandlesToBytes(splitIndex - handleIndex); // First, the target handle must be removed. Its data can still be used to determine the new handles. + RegionSignal signal = handle.PreAction; handle.Dispose(); RegionHandle splitLow = _tracking.BeginTracking(address, size); splitLow.Parent = this; + if (signal != null) + { + splitLow.RegisterAction(signal); + } _handles[handleIndex] = splitLow; RegionHandle splitHigh = _tracking.BeginTracking(address + size, handle.Size - size); splitHigh.Parent = this; + if (signal != null) + { + splitHigh.RegisterAction(signal); + } _handles[splitIndex] = splitHigh; } diff --git a/Ryujinx.Memory/Tracking/VirtualRegion.cs b/Ryujinx.Memory/Tracking/VirtualRegion.cs index 90fb55d6..15a11568 100644 --- a/Ryujinx.Memory/Tracking/VirtualRegion.cs +++ b/Ryujinx.Memory/Tracking/VirtualRegion.cs @@ -22,12 +22,12 @@ namespace Ryujinx.Memory.Tracking public override void Signal(ulong address, ulong size, bool write) { - _tracking.ProtectVirtualRegion(this, MemoryPermission.ReadAndWrite); // Remove our protection immedately. - foreach (var handle in Handles) { handle.Signal(address, size, write); } + + UpdateProtection(); } /// <summary> |
