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.
This commit is contained in:
parent
c4f56c5704
commit
a1f77a5b6a
28 changed files with 1073 additions and 57 deletions
|
@ -12,16 +12,16 @@ namespace Ryujinx.Memory.Range
|
|||
{
|
||||
private const int ArrayGrowthSize = 32;
|
||||
|
||||
private readonly List<T> _items;
|
||||
protected readonly List<T> Items;
|
||||
|
||||
public int Count => _items.Count;
|
||||
public int Count => Items.Count;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new range list.
|
||||
/// </summary>
|
||||
public RangeList()
|
||||
{
|
||||
_items = new List<T>();
|
||||
Items = new List<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -37,7 +37,7 @@ namespace Ryujinx.Memory.Range
|
|||
index = ~index;
|
||||
}
|
||||
|
||||
_items.Insert(index, item);
|
||||
Items.Insert(index, item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -51,21 +51,21 @@ namespace Ryujinx.Memory.Range
|
|||
|
||||
if (index >= 0)
|
||||
{
|
||||
while (index > 0 && _items[index - 1].Address == item.Address)
|
||||
while (index > 0 && Items[index - 1].Address == item.Address)
|
||||
{
|
||||
index--;
|
||||
}
|
||||
|
||||
while (index < _items.Count)
|
||||
while (index < Items.Count)
|
||||
{
|
||||
if (_items[index].Equals(item))
|
||||
if (Items[index].Equals(item))
|
||||
{
|
||||
_items.RemoveAt(index);
|
||||
Items.RemoveAt(index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_items[index].Address > item.Address)
|
||||
if (Items[index].Address > item.Address)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ namespace Ryujinx.Memory.Range
|
|||
return default(T);
|
||||
}
|
||||
|
||||
return _items[index];
|
||||
return Items[index];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -137,7 +137,7 @@ namespace Ryujinx.Memory.Range
|
|||
|
||||
ulong endAddress = address + size;
|
||||
|
||||
foreach (T item in _items)
|
||||
foreach (T item in Items)
|
||||
{
|
||||
if (item.Address >= endAddress)
|
||||
{
|
||||
|
@ -196,7 +196,7 @@ namespace Ryujinx.Memory.Range
|
|||
|
||||
if (index >= 0)
|
||||
{
|
||||
while (index > 0 && _items[index - 1].OverlapsWith(address, size))
|
||||
while (index > 0 && Items[index - 1].OverlapsWith(address, size))
|
||||
{
|
||||
index--;
|
||||
}
|
||||
|
@ -208,9 +208,9 @@ namespace Ryujinx.Memory.Range
|
|||
Array.Resize(ref output, outputIndex + ArrayGrowthSize);
|
||||
}
|
||||
|
||||
output[outputIndex++] = _items[index++];
|
||||
output[outputIndex++] = Items[index++];
|
||||
}
|
||||
while (index < _items.Count && _items[index].OverlapsWith(address, size));
|
||||
while (index < Items.Count && Items[index].OverlapsWith(address, size));
|
||||
}
|
||||
|
||||
return outputIndex;
|
||||
|
@ -230,14 +230,14 @@ namespace Ryujinx.Memory.Range
|
|||
|
||||
if (index >= 0)
|
||||
{
|
||||
while (index > 0 && _items[index - 1].Address == address)
|
||||
while (index > 0 && Items[index - 1].Address == address)
|
||||
{
|
||||
index--;
|
||||
}
|
||||
|
||||
while (index < _items.Count)
|
||||
while (index < Items.Count)
|
||||
{
|
||||
T overlap = _items[index++];
|
||||
T overlap = Items[index++];
|
||||
|
||||
if (overlap.Address != address)
|
||||
{
|
||||
|
@ -264,7 +264,7 @@ namespace Ryujinx.Memory.Range
|
|||
private int BinarySearch(ulong address)
|
||||
{
|
||||
int left = 0;
|
||||
int right = _items.Count - 1;
|
||||
int right = Items.Count - 1;
|
||||
|
||||
while (left <= right)
|
||||
{
|
||||
|
@ -272,7 +272,7 @@ namespace Ryujinx.Memory.Range
|
|||
|
||||
int middle = left + (range >> 1);
|
||||
|
||||
T item = _items[middle];
|
||||
T item = Items[middle];
|
||||
|
||||
if (item.Address == address)
|
||||
{
|
||||
|
@ -301,7 +301,7 @@ namespace Ryujinx.Memory.Range
|
|||
private int BinarySearch(ulong address, ulong size)
|
||||
{
|
||||
int left = 0;
|
||||
int right = _items.Count - 1;
|
||||
int right = Items.Count - 1;
|
||||
|
||||
while (left <= right)
|
||||
{
|
||||
|
@ -309,7 +309,7 @@ namespace Ryujinx.Memory.Range
|
|||
|
||||
int middle = left + (range >> 1);
|
||||
|
||||
T item = _items[middle];
|
||||
T item = Items[middle];
|
||||
|
||||
if (item.OverlapsWith(address, size))
|
||||
{
|
||||
|
@ -331,12 +331,12 @@ namespace Ryujinx.Memory.Range
|
|||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return _items.GetEnumerator();
|
||||
return Items.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return _items.GetEnumerator();
|
||||
return Items.GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue