From c61c1ea8980f0a97ea4d77a5465745d7103e2452 Mon Sep 17 00:00:00 2001 From: riperiperi Date: Thu, 7 Oct 2021 00:00:56 +0100 Subject: [PATCH 1/2] Reregister flush actions when taking a buffer's modified range list. Fixes a regression from #2663 where buffer flush would not happen after a resize. Specifically caused the world map in Yoshi's Crafted World to flash. I have other planned changes to this class so this might change soon, but this regression could affect a lot so it couldn't wait. --- Ryujinx.Graphics.Gpu/Memory/Buffer.cs | 26 +++++++++++-------- .../Memory/BufferModifiedRangeList.cs | 16 ++++++++++++ 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/Ryujinx.Graphics.Gpu/Memory/Buffer.cs b/Ryujinx.Graphics.Gpu/Memory/Buffer.cs index 0eaf0123..81f70684 100644 --- a/Ryujinx.Graphics.Gpu/Memory/Buffer.cs +++ b/Ryujinx.Graphics.Gpu/Memory/Buffer.cs @@ -299,24 +299,28 @@ namespace Ryujinx.Graphics.Gpu.Memory _syncActionRegistered = true; } + Action registerRangeAction = (ulong address, ulong size) => + { + if (_useGranular) + { + _memoryTrackingGranular.RegisterAction(address, size, _externalFlushDelegate); + } + else + { + _memoryTracking.RegisterAction(_externalFlushDelegate); + } + }; + if (_modifiedRanges == null) { _modifiedRanges = from._modifiedRanges; + _modifiedRanges.ReregisterRanges(registerRangeAction); + from._modifiedRanges = null; } else { - _modifiedRanges.InheritRanges(from._modifiedRanges, (ulong address, ulong size) => - { - if (_useGranular) - { - _memoryTrackingGranular.RegisterAction(address, size, _externalFlushDelegate); - } - else - { - _memoryTracking.RegisterAction(_externalFlushDelegate); - } - }); + _modifiedRanges.InheritRanges(from._modifiedRanges, registerRangeAction); } } } diff --git a/Ryujinx.Graphics.Gpu/Memory/BufferModifiedRangeList.cs b/Ryujinx.Graphics.Gpu/Memory/BufferModifiedRangeList.cs index 84cf0dd8..faaccf13 100644 --- a/Ryujinx.Graphics.Gpu/Memory/BufferModifiedRangeList.cs +++ b/Ryujinx.Graphics.Gpu/Memory/BufferModifiedRangeList.cs @@ -318,6 +318,22 @@ namespace Ryujinx.Graphics.Gpu.Memory } } + /// + /// Calls the given action for modified ranges that aren't from the current sync number. + /// + /// The action to call for each modified range + public void ReregisterRanges(Action rangeAction) + { + ulong currentSync = _context.SyncNumber; + foreach (BufferModifiedRange range in this) + { + if (range.SyncNumber != currentSync) + { + rangeAction(range.Address, range.Size); + } + } + } + private void ClearPart(BufferModifiedRange overlap, ulong address, ulong endAddress) { Remove(overlap); From a4956591ec485e9b23ded32a853f2a63af92b769 Mon Sep 17 00:00:00 2001 From: riperiperi Date: Thu, 7 Oct 2021 01:13:51 +0100 Subject: [PATCH 2/2] Avoid potential race --- .../Memory/BufferModifiedRangeList.cs | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/Ryujinx.Graphics.Gpu/Memory/BufferModifiedRangeList.cs b/Ryujinx.Graphics.Gpu/Memory/BufferModifiedRangeList.cs index faaccf13..b9b533fb 100644 --- a/Ryujinx.Graphics.Gpu/Memory/BufferModifiedRangeList.cs +++ b/Ryujinx.Graphics.Gpu/Memory/BufferModifiedRangeList.cs @@ -324,9 +324,27 @@ namespace Ryujinx.Graphics.Gpu.Memory /// The action to call for each modified range public void ReregisterRanges(Action rangeAction) { - ulong currentSync = _context.SyncNumber; - foreach (BufferModifiedRange range in this) + ref var ranges = ref ThreadStaticArray.Get(); + + // Range list must be consistent for this operation. + lock (_lock) { + if (ranges.Length < Count) + { + Array.Resize(ref ranges, Count); + } + + int i = 0; + foreach (BufferModifiedRange range in this) + { + ranges[i++] = range; + } + } + + ulong currentSync = _context.SyncNumber; + for (int i = 0; i < Count; i++) + { + BufferModifiedRange range = ranges[i]; if (range.SyncNumber != currentSync) { rangeAction(range.Address, range.Size);