Support for resources on non-contiguous GPU memory regions (#1905)
* Support for resources on non-contiguous GPU memory regions * Implement MultiRange physical addresses, only used with a single range for now * Actually use non-contiguous ranges * GetPhysicalRegions fixes * Documentation and remove Address property from TextureInfo * Finish implementing GetWritableRegion * Fix typo
This commit is contained in:
parent
3bad321d2b
commit
c4f56c5704
18 changed files with 1141 additions and 167 deletions
|
@ -1,6 +1,7 @@
|
|||
using Ryujinx.Cpu;
|
||||
using Ryujinx.Cpu.Tracking;
|
||||
using Ryujinx.Memory;
|
||||
using Ryujinx.Memory.Range;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
@ -38,6 +39,37 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
return _cpuMemory.GetSpan(address, size, tracked);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a span of data from the application process.
|
||||
/// </summary>
|
||||
/// <param name="range">Ranges of physical memory where the data is located</param>
|
||||
/// <param name="tracked">True if read tracking is triggered on the span</param>
|
||||
/// <returns>A read only span of the data at the specified memory location</returns>
|
||||
public ReadOnlySpan<byte> GetSpan(MultiRange range, bool tracked = false)
|
||||
{
|
||||
if (range.Count == 1)
|
||||
{
|
||||
var singleRange = range.GetSubRange(0);
|
||||
return _cpuMemory.GetSpan(singleRange.Address, (int)singleRange.Size, tracked);
|
||||
}
|
||||
else
|
||||
{
|
||||
Span<byte> data = new byte[range.GetSize()];
|
||||
|
||||
int offset = 0;
|
||||
|
||||
for (int i = 0; i < range.Count; i++)
|
||||
{
|
||||
var currentRange = range.GetSubRange(i);
|
||||
int size = (int)currentRange.Size;
|
||||
_cpuMemory.GetSpan(currentRange.Address, size, tracked).CopyTo(data.Slice(offset, size));
|
||||
offset += size;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a writable region from the application process.
|
||||
/// </summary>
|
||||
|
@ -70,6 +102,16 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
_cpuMemory.Write(address, data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes data to the application process.
|
||||
/// </summary>
|
||||
/// <param name="range">Ranges of physical memory where the data is located</param>
|
||||
/// <param name="data">Data to be written</param>
|
||||
public void Write(MultiRange range, ReadOnlySpan<byte> data)
|
||||
{
|
||||
WriteImpl(range, data, _cpuMemory.Write);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes data to the application process, without any tracking.
|
||||
/// </summary>
|
||||
|
@ -80,6 +122,45 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
_cpuMemory.WriteUntracked(address, data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes data to the application process, without any tracking.
|
||||
/// </summary>
|
||||
/// <param name="range">Ranges of physical memory where the data is located</param>
|
||||
/// <param name="data">Data to be written</param>
|
||||
public void WriteUntracked(MultiRange range, ReadOnlySpan<byte> data)
|
||||
{
|
||||
WriteImpl(range, data, _cpuMemory.WriteUntracked);
|
||||
}
|
||||
|
||||
private delegate void WriteCallback(ulong address, ReadOnlySpan<byte> data);
|
||||
|
||||
/// <summary>
|
||||
/// Writes data to the application process, using the supplied callback method.
|
||||
/// </summary>
|
||||
/// <param name="range">Ranges of physical memory where the data is located</param>
|
||||
/// <param name="data">Data to be written</param>
|
||||
/// <param name="writeCallback">Callback method that will perform the write</param>
|
||||
private void WriteImpl(MultiRange range, ReadOnlySpan<byte> data, WriteCallback writeCallback)
|
||||
{
|
||||
if (range.Count == 1)
|
||||
{
|
||||
var singleRange = range.GetSubRange(0);
|
||||
writeCallback(singleRange.Address, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
int offset = 0;
|
||||
|
||||
for (int i = 0; i < range.Count; i++)
|
||||
{
|
||||
var currentRange = range.GetSubRange(i);
|
||||
int size = (int)currentRange.Size;
|
||||
writeCallback(currentRange.Address, data.Slice(offset, size));
|
||||
offset += size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Obtains a memory tracking handle for the given virtual region. This should be disposed when finished with.
|
||||
/// </summary>
|
||||
|
@ -91,6 +172,24 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
return _cpuMemory.BeginTracking(address, size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Obtains a memory tracking handle for the given virtual region. This should be disposed when finished with.
|
||||
/// </summary>
|
||||
/// <param name="range">Ranges of physical memory where the data is located</param>
|
||||
/// <returns>The memory tracking handle</returns>
|
||||
public GpuRegionHandle BeginTracking(MultiRange range)
|
||||
{
|
||||
var cpuRegionHandles = new CpuRegionHandle[range.Count];
|
||||
|
||||
for (int i = 0; i < range.Count; i++)
|
||||
{
|
||||
var currentRange = range.GetSubRange(i);
|
||||
cpuRegionHandles[i] = _cpuMemory.BeginTracking(currentRange.Address, currentRange.Size);
|
||||
}
|
||||
|
||||
return new GpuRegionHandle(cpuRegionHandles);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Obtains a memory tracking handle for the given virtual region, with a specified granularity. This should be disposed when finished with.
|
||||
/// </summary>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue