mirror of
https://github.com/GreemDev/Ryujinx.git
synced 2024-11-27 19:30:50 +01:00
Add a separate device memory manager (#6153)
* Add a separate device memory manager * Still need this * Device writes are always tracked * Device writes are always tracked (2) * Rename more instances of gmm to mm
This commit is contained in:
parent
90455a05e6
commit
f241f88558
395
src/Ryujinx.Graphics.Device/DeviceMemoryManager.cs
Normal file
395
src/Ryujinx.Graphics.Device/DeviceMemoryManager.cs
Normal file
@ -0,0 +1,395 @@
|
||||
using Ryujinx.Memory;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Graphics.Device
|
||||
{
|
||||
/// <summary>
|
||||
/// Device memory manager.
|
||||
/// </summary>
|
||||
public class DeviceMemoryManager : IWritableBlock
|
||||
{
|
||||
private const int PtLvl0Bits = 10;
|
||||
private const int PtLvl1Bits = 10;
|
||||
public const int PtPageBits = 12;
|
||||
|
||||
private const ulong PtLvl0Size = 1UL << PtLvl0Bits;
|
||||
private const ulong PtLvl1Size = 1UL << PtLvl1Bits;
|
||||
public const ulong PageSize = 1UL << PtPageBits;
|
||||
|
||||
private const ulong PtLvl0Mask = PtLvl0Size - 1;
|
||||
private const ulong PtLvl1Mask = PtLvl1Size - 1;
|
||||
public const ulong PageMask = PageSize - 1;
|
||||
|
||||
private const int PtLvl0Bit = PtPageBits + PtLvl1Bits;
|
||||
private const int PtLvl1Bit = PtPageBits;
|
||||
private const int AddressSpaceBits = PtPageBits + PtLvl1Bits + PtLvl0Bits;
|
||||
|
||||
public const ulong PteUnmapped = ulong.MaxValue;
|
||||
|
||||
private readonly ulong[][] _pageTable;
|
||||
|
||||
private readonly IVirtualMemoryManager _physical;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the GPU memory manager.
|
||||
/// </summary>
|
||||
/// <param name="physicalMemory">Physical memory that this memory manager will map into</param>
|
||||
public DeviceMemoryManager(IVirtualMemoryManager physicalMemory)
|
||||
{
|
||||
_physical = physicalMemory;
|
||||
_pageTable = new ulong[PtLvl0Size][];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads data from GPU mapped memory.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the data</typeparam>
|
||||
/// <param name="va">GPU virtual address where the data is located</param>
|
||||
/// <returns>The data at the specified memory location</returns>
|
||||
public T Read<T>(ulong va) where T : unmanaged
|
||||
{
|
||||
int size = Unsafe.SizeOf<T>();
|
||||
|
||||
if (IsContiguous(va, size))
|
||||
{
|
||||
return _physical.Read<T>(Translate(va));
|
||||
}
|
||||
else
|
||||
{
|
||||
Span<byte> data = new byte[size];
|
||||
|
||||
ReadImpl(va, data);
|
||||
|
||||
return MemoryMarshal.Cast<byte, T>(data)[0];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a read-only span of data from GPU mapped memory.
|
||||
/// </summary>
|
||||
/// <param name="va">GPU virtual address where the data is located</param>
|
||||
/// <param name="size">Size of the data</param>
|
||||
/// <returns>The span of the data at the specified memory location</returns>
|
||||
public ReadOnlySpan<byte> GetSpan(ulong va, int size)
|
||||
{
|
||||
if (IsContiguous(va, size))
|
||||
{
|
||||
return _physical.GetSpan(Translate(va), size);
|
||||
}
|
||||
else
|
||||
{
|
||||
Span<byte> data = new byte[size];
|
||||
|
||||
ReadImpl(va, data);
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads data from a possibly non-contiguous region of GPU mapped memory.
|
||||
/// </summary>
|
||||
/// <param name="va">GPU virtual address of the data</param>
|
||||
/// <param name="data">Span to write the read data into</param>
|
||||
private void ReadImpl(ulong va, Span<byte> data)
|
||||
{
|
||||
if (data.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int offset = 0, size;
|
||||
|
||||
if ((va & PageMask) != 0)
|
||||
{
|
||||
ulong pa = Translate(va);
|
||||
|
||||
size = Math.Min(data.Length, (int)PageSize - (int)(va & PageMask));
|
||||
|
||||
if (pa != PteUnmapped && _physical.IsMapped(pa))
|
||||
{
|
||||
_physical.GetSpan(pa, size).CopyTo(data[..size]);
|
||||
}
|
||||
|
||||
offset += size;
|
||||
}
|
||||
|
||||
for (; offset < data.Length; offset += size)
|
||||
{
|
||||
ulong pa = Translate(va + (ulong)offset);
|
||||
|
||||
size = Math.Min(data.Length - offset, (int)PageSize);
|
||||
|
||||
if (pa != PteUnmapped && _physical.IsMapped(pa))
|
||||
{
|
||||
_physical.GetSpan(pa, size).CopyTo(data.Slice(offset, size));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a writable region from GPU mapped memory.
|
||||
/// </summary>
|
||||
/// <param name="va">Start address of the range</param>
|
||||
/// <param name="size">Size in bytes to be range</param>
|
||||
/// <returns>A writable region with the data at the specified memory location</returns>
|
||||
public WritableRegion GetWritableRegion(ulong va, int size)
|
||||
{
|
||||
if (IsContiguous(va, size))
|
||||
{
|
||||
return _physical.GetWritableRegion(Translate(va), size, tracked: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Memory<byte> memory = new byte[size];
|
||||
|
||||
GetSpan(va, size).CopyTo(memory.Span);
|
||||
|
||||
return new WritableRegion(this, va, memory, tracked: true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes data to GPU mapped memory.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the data</typeparam>
|
||||
/// <param name="va">GPU virtual address to write the value into</param>
|
||||
/// <param name="value">The value to be written</param>
|
||||
public void Write<T>(ulong va, T value) where T : unmanaged
|
||||
{
|
||||
Write(va, MemoryMarshal.Cast<T, byte>(MemoryMarshal.CreateSpan(ref value, 1)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes data to GPU mapped memory.
|
||||
/// </summary>
|
||||
/// <param name="va">GPU virtual address to write the data into</param>
|
||||
/// <param name="data">The data to be written</param>
|
||||
public void Write(ulong va, ReadOnlySpan<byte> data)
|
||||
{
|
||||
if (IsContiguous(va, data.Length))
|
||||
{
|
||||
_physical.Write(Translate(va), data);
|
||||
}
|
||||
else
|
||||
{
|
||||
int offset = 0, size;
|
||||
|
||||
if ((va & PageMask) != 0)
|
||||
{
|
||||
ulong pa = Translate(va);
|
||||
|
||||
size = Math.Min(data.Length, (int)PageSize - (int)(va & PageMask));
|
||||
|
||||
if (pa != PteUnmapped && _physical.IsMapped(pa))
|
||||
{
|
||||
_physical.Write(pa, data[..size]);
|
||||
}
|
||||
|
||||
offset += size;
|
||||
}
|
||||
|
||||
for (; offset < data.Length; offset += size)
|
||||
{
|
||||
ulong pa = Translate(va + (ulong)offset);
|
||||
|
||||
size = Math.Min(data.Length - offset, (int)PageSize);
|
||||
|
||||
if (pa != PteUnmapped && _physical.IsMapped(pa))
|
||||
{
|
||||
_physical.Write(pa, data.Slice(offset, size));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes data to GPU mapped memory without write tracking.
|
||||
/// </summary>
|
||||
/// <param name="va">GPU virtual address to write the data into</param>
|
||||
/// <param name="data">The data to be written</param>
|
||||
public void WriteUntracked(ulong va, ReadOnlySpan<byte> data)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps a given range of pages to the specified CPU virtual address.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// All addresses and sizes must be page aligned.
|
||||
/// </remarks>
|
||||
/// <param name="pa">CPU virtual address to map into</param>
|
||||
/// <param name="va">GPU virtual address to be mapped</param>
|
||||
/// <param name="kind">Kind of the resource located at the mapping</param>
|
||||
public void Map(ulong pa, ulong va, ulong size)
|
||||
{
|
||||
lock (_pageTable)
|
||||
{
|
||||
for (ulong offset = 0; offset < size; offset += PageSize)
|
||||
{
|
||||
SetPte(va + offset, PackPte(pa + offset));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unmaps a given range of pages at the specified GPU virtual memory region.
|
||||
/// </summary>
|
||||
/// <param name="va">GPU virtual address to unmap</param>
|
||||
/// <param name="size">Size in bytes of the region being unmapped</param>
|
||||
public void Unmap(ulong va, ulong size)
|
||||
{
|
||||
lock (_pageTable)
|
||||
{
|
||||
for (ulong offset = 0; offset < size; offset += PageSize)
|
||||
{
|
||||
SetPte(va + offset, PteUnmapped);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a region of GPU mapped memory is contiguous.
|
||||
/// </summary>
|
||||
/// <param name="va">GPU virtual address of the region</param>
|
||||
/// <param name="size">Size of the region</param>
|
||||
/// <returns>True if the region is contiguous, false otherwise</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private bool IsContiguous(ulong va, int size)
|
||||
{
|
||||
if (!ValidateAddress(va) || GetPte(va) == PteUnmapped)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ulong endVa = (va + (ulong)size + PageMask) & ~PageMask;
|
||||
|
||||
va &= ~PageMask;
|
||||
|
||||
int pages = (int)((endVa - va) / PageSize);
|
||||
|
||||
for (int page = 0; page < pages - 1; page++)
|
||||
{
|
||||
if (!ValidateAddress(va + PageSize) || GetPte(va + PageSize) == PteUnmapped)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Translate(va) + PageSize != Translate(va + PageSize))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
va += PageSize;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates a GPU virtual address.
|
||||
/// </summary>
|
||||
/// <param name="va">Address to validate</param>
|
||||
/// <returns>True if the address is valid, false otherwise</returns>
|
||||
private static bool ValidateAddress(ulong va)
|
||||
{
|
||||
return va < (1UL << AddressSpaceBits);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a given page is mapped.
|
||||
/// </summary>
|
||||
/// <param name="va">GPU virtual address of the page to check</param>
|
||||
/// <returns>True if the page is mapped, false otherwise</returns>
|
||||
public bool IsMapped(ulong va)
|
||||
{
|
||||
return Translate(va) != PteUnmapped;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Translates a GPU virtual address to a CPU virtual address.
|
||||
/// </summary>
|
||||
/// <param name="va">GPU virtual address to be translated</param>
|
||||
/// <returns>CPU virtual address, or <see cref="PteUnmapped"/> if unmapped</returns>
|
||||
public ulong Translate(ulong va)
|
||||
{
|
||||
if (!ValidateAddress(va))
|
||||
{
|
||||
return PteUnmapped;
|
||||
}
|
||||
|
||||
ulong pte = GetPte(va);
|
||||
|
||||
if (pte == PteUnmapped)
|
||||
{
|
||||
return PteUnmapped;
|
||||
}
|
||||
|
||||
return UnpackPaFromPte(pte) + (va & PageMask);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Page Table entry for a given GPU virtual address.
|
||||
/// </summary>
|
||||
/// <param name="va">GPU virtual address</param>
|
||||
/// <returns>Page table entry (CPU virtual address)</returns>
|
||||
private ulong GetPte(ulong va)
|
||||
{
|
||||
ulong l0 = (va >> PtLvl0Bit) & PtLvl0Mask;
|
||||
ulong l1 = (va >> PtLvl1Bit) & PtLvl1Mask;
|
||||
|
||||
if (_pageTable[l0] == null)
|
||||
{
|
||||
return PteUnmapped;
|
||||
}
|
||||
|
||||
return _pageTable[l0][l1];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a Page Table entry at a given GPU virtual address.
|
||||
/// </summary>
|
||||
/// <param name="va">GPU virtual address</param>
|
||||
/// <param name="pte">Page table entry (CPU virtual address)</param>
|
||||
private void SetPte(ulong va, ulong pte)
|
||||
{
|
||||
ulong l0 = (va >> PtLvl0Bit) & PtLvl0Mask;
|
||||
ulong l1 = (va >> PtLvl1Bit) & PtLvl1Mask;
|
||||
|
||||
if (_pageTable[l0] == null)
|
||||
{
|
||||
_pageTable[l0] = new ulong[PtLvl1Size];
|
||||
|
||||
for (ulong index = 0; index < PtLvl1Size; index++)
|
||||
{
|
||||
_pageTable[l0][index] = PteUnmapped;
|
||||
}
|
||||
}
|
||||
|
||||
_pageTable[l0][l1] = pte;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a page table entry from a physical address and kind.
|
||||
/// </summary>
|
||||
/// <param name="pa">Physical address</param>
|
||||
/// <returns>Page table entry</returns>
|
||||
private static ulong PackPte(ulong pa)
|
||||
{
|
||||
return pa;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unpacks physical address from a page table entry.
|
||||
/// </summary>
|
||||
/// <param name="pte">Page table entry</param>
|
||||
/// <returns>Physical address</returns>
|
||||
private static ulong UnpackPaFromPte(ulong pte)
|
||||
{
|
||||
return pte;
|
||||
}
|
||||
}
|
||||
}
|
39
src/Ryujinx.Graphics.Device/ISynchronizationManager.cs
Normal file
39
src/Ryujinx.Graphics.Device/ISynchronizationManager.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using Ryujinx.Common.Logging;
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Ryujinx.Graphics.Device
|
||||
{
|
||||
/// <summary>
|
||||
/// Synchronization manager interface.
|
||||
/// </summary>
|
||||
public interface ISynchronizationManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Increment the value of a syncpoint with a given id.
|
||||
/// </summary>
|
||||
/// <param name="id">The id of the syncpoint</param>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">Thrown when id >= MaxHardwareSyncpoints</exception>
|
||||
/// <returns>The incremented value of the syncpoint</returns>
|
||||
uint IncrementSyncpoint(uint id);
|
||||
|
||||
/// <summary>
|
||||
/// Get the value of a syncpoint with a given id.
|
||||
/// </summary>
|
||||
/// <param name="id">The id of the syncpoint</param>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">Thrown when id >= MaxHardwareSyncpoints</exception>
|
||||
/// <returns>The value of the syncpoint</returns>
|
||||
uint GetSyncpointValue(uint id);
|
||||
|
||||
/// <summary>
|
||||
/// Wait on a syncpoint with a given id at a target threshold.
|
||||
/// The callback will be called once the threshold is reached and will automatically be unregistered.
|
||||
/// </summary>
|
||||
/// <param name="id">The id of the syncpoint</param>
|
||||
/// <param name="threshold">The target threshold</param>
|
||||
/// <param name="timeout">The timeout</param>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">Thrown when id >= MaxHardwareSyncpoints</exception>
|
||||
/// <returns>True if timed out</returns>
|
||||
bool WaitOnSyncpoint(uint id, uint threshold, TimeSpan timeout);
|
||||
}
|
||||
}
|
@ -4,4 +4,8 @@
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ryujinx.Memory\Ryujinx.Memory.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Graphics.Device;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Graphics.Gpu.Engine.GPFifo;
|
||||
using Ryujinx.Graphics.Gpu.Memory;
|
||||
@ -163,6 +164,22 @@ namespace Ryujinx.Graphics.Gpu
|
||||
return new MemoryManager(physicalMemory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new device memory manager.
|
||||
/// </summary>
|
||||
/// <param name="pid">ID of the process that owns the memory manager</param>
|
||||
/// <returns>The memory manager</returns>
|
||||
/// <exception cref="ArgumentException">Thrown when <paramref name="pid"/> is invalid</exception>
|
||||
public DeviceMemoryManager CreateDeviceMemoryManager(ulong pid)
|
||||
{
|
||||
if (!PhysicalMemoryRegistry.TryGetValue(pid, out var physicalMemory))
|
||||
{
|
||||
throw new ArgumentException("The PID is invalid or the process was not registered", nameof(pid));
|
||||
}
|
||||
|
||||
return physicalMemory.CreateDeviceMemoryManager();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers virtual memory used by a process for GPU memory access, caching and read/write tracking.
|
||||
/// </summary>
|
||||
|
@ -329,49 +329,6 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes data to GPU mapped memory, stopping at the first unmapped page at the memory region, if any.
|
||||
/// </summary>
|
||||
/// <param name="va">GPU virtual address to write the data into</param>
|
||||
/// <param name="data">The data to be written</param>
|
||||
public void WriteMapped(ulong va, ReadOnlySpan<byte> data)
|
||||
{
|
||||
if (IsContiguous(va, data.Length))
|
||||
{
|
||||
Physical.Write(Translate(va), data);
|
||||
}
|
||||
else
|
||||
{
|
||||
int offset = 0, size;
|
||||
|
||||
if ((va & PageMask) != 0)
|
||||
{
|
||||
ulong pa = Translate(va);
|
||||
|
||||
size = Math.Min(data.Length, (int)PageSize - (int)(va & PageMask));
|
||||
|
||||
if (pa != PteUnmapped && Physical.IsMapped(pa))
|
||||
{
|
||||
Physical.Write(pa, data[..size]);
|
||||
}
|
||||
|
||||
offset += size;
|
||||
}
|
||||
|
||||
for (; offset < data.Length; offset += size)
|
||||
{
|
||||
ulong pa = Translate(va + (ulong)offset);
|
||||
|
||||
size = Math.Min(data.Length - offset, (int)PageSize);
|
||||
|
||||
if (pa != PteUnmapped && Physical.IsMapped(pa))
|
||||
{
|
||||
Physical.Write(pa, data.Slice(offset, size));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs remap actions that are added to an unmap event.
|
||||
/// These must run after the mapping completes.
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Ryujinx.Cpu;
|
||||
using Ryujinx.Graphics.Device;
|
||||
using Ryujinx.Graphics.Gpu.Image;
|
||||
using Ryujinx.Graphics.Gpu.Shader;
|
||||
using Ryujinx.Memory;
|
||||
@ -82,6 +83,15 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new device memory manager.
|
||||
/// </summary>
|
||||
/// <returns>The memory manager</returns>
|
||||
public DeviceMemoryManager CreateDeviceMemoryManager()
|
||||
{
|
||||
return new DeviceMemoryManager(_cpuMemory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a host pointer for a given range of application memory.
|
||||
/// If the memory region is not a single contiguous block, this method returns 0.
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Graphics.Device;
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
@ -7,7 +8,7 @@ namespace Ryujinx.Graphics.Gpu.Synchronization
|
||||
/// <summary>
|
||||
/// GPU synchronization manager.
|
||||
/// </summary>
|
||||
public class SynchronizationManager
|
||||
public class SynchronizationManager : ISynchronizationManager
|
||||
{
|
||||
/// <summary>
|
||||
/// The maximum number of syncpoints supported by the GM20B.
|
||||
@ -29,12 +30,7 @@ namespace Ryujinx.Graphics.Gpu.Synchronization
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Increment the value of a syncpoint with a given id.
|
||||
/// </summary>
|
||||
/// <param name="id">The id of the syncpoint</param>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">Thrown when id >= MaxHardwareSyncpoints</exception>
|
||||
/// <returns>The incremented value of the syncpoint</returns>
|
||||
/// <inheritdoc/>
|
||||
public uint IncrementSyncpoint(uint id)
|
||||
{
|
||||
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(id, (uint)MaxHardwareSyncpoints);
|
||||
@ -42,12 +38,7 @@ namespace Ryujinx.Graphics.Gpu.Synchronization
|
||||
return _syncpoints[id].Increment();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the value of a syncpoint with a given id.
|
||||
/// </summary>
|
||||
/// <param name="id">The id of the syncpoint</param>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">Thrown when id >= MaxHardwareSyncpoints</exception>
|
||||
/// <returns>The value of the syncpoint</returns>
|
||||
/// <inheritdoc/>
|
||||
public uint GetSyncpointValue(uint id)
|
||||
{
|
||||
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(id, (uint)MaxHardwareSyncpoints);
|
||||
@ -84,15 +75,7 @@ namespace Ryujinx.Graphics.Gpu.Synchronization
|
||||
_syncpoints[id].UnregisterCallback(waiterInformation);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wait on a syncpoint with a given id at a target threshold.
|
||||
/// The callback will be called once the threshold is reached and will automatically be unregistered.
|
||||
/// </summary>
|
||||
/// <param name="id">The id of the syncpoint</param>
|
||||
/// <param name="threshold">The target threshold</param>
|
||||
/// <param name="timeout">The timeout</param>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">Thrown when id >= MaxHardwareSyncpoints</exception>
|
||||
/// <returns>True if timed out</returns>
|
||||
/// <inheritdoc/>
|
||||
public bool WaitOnSyncpoint(uint id, uint threshold, TimeSpan timeout)
|
||||
{
|
||||
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(id, (uint)MaxHardwareSyncpoints);
|
||||
|
@ -1,5 +1,4 @@
|
||||
using Ryujinx.Graphics.Device;
|
||||
using Ryujinx.Graphics.Gpu.Synchronization;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
@ -7,10 +6,10 @@ namespace Ryujinx.Graphics.Host1x
|
||||
{
|
||||
public class Host1xClass : IDeviceState
|
||||
{
|
||||
private readonly SynchronizationManager _syncMgr;
|
||||
private readonly ISynchronizationManager _syncMgr;
|
||||
private readonly DeviceState<Host1xClassRegisters> _state;
|
||||
|
||||
public Host1xClass(SynchronizationManager syncMgr)
|
||||
public Host1xClass(ISynchronizationManager syncMgr)
|
||||
{
|
||||
_syncMgr = syncMgr;
|
||||
_state = new DeviceState<Host1xClassRegisters>(new Dictionary<string, RwCallback>
|
||||
|
@ -1,7 +1,6 @@
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Graphics.Device;
|
||||
using Ryujinx.Graphics.Gpu.Synchronization;
|
||||
using System;
|
||||
using System.Numerics;
|
||||
|
||||
@ -35,7 +34,7 @@ namespace Ryujinx.Graphics.Host1x
|
||||
private int _mask;
|
||||
private bool _incrementing;
|
||||
|
||||
public Host1xDevice(SynchronizationManager syncMgr)
|
||||
public Host1xDevice(ISynchronizationManager syncMgr)
|
||||
{
|
||||
_syncptIncrMgr = new SyncptIncrManager(syncMgr);
|
||||
_commandQueue = new AsyncWorkQueue<Command>(Process, "Ryujinx.Host1xProcessor");
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ryujinx.Graphics.Device\Ryujinx.Graphics.Device.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Graphics.Gpu\Ryujinx.Graphics.Gpu.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -1,11 +1,11 @@
|
||||
using Ryujinx.Graphics.Gpu.Synchronization;
|
||||
using Ryujinx.Graphics.Device;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Graphics.Host1x
|
||||
{
|
||||
class SyncptIncrManager
|
||||
{
|
||||
private readonly SynchronizationManager _syncMgr;
|
||||
private readonly ISynchronizationManager _syncMgr;
|
||||
|
||||
private readonly struct SyncptIncr
|
||||
{
|
||||
@ -27,7 +27,7 @@ namespace Ryujinx.Graphics.Host1x
|
||||
|
||||
private uint _currentId;
|
||||
|
||||
public SyncptIncrManager(SynchronizationManager syncMgr)
|
||||
public SyncptIncrManager(ISynchronizationManager syncMgr)
|
||||
{
|
||||
_syncMgr = syncMgr;
|
||||
}
|
||||
|
@ -12,10 +12,10 @@ namespace Ryujinx.Graphics.Nvdec
|
||||
|
||||
public static void Decode(NvdecDecoderContext context, ResourceManager rm, ref NvdecRegisters state)
|
||||
{
|
||||
PictureInfo pictureInfo = rm.Gmm.DeviceRead<PictureInfo>(state.SetDrvPicSetupOffset);
|
||||
PictureInfo pictureInfo = rm.MemoryManager.DeviceRead<PictureInfo>(state.SetDrvPicSetupOffset);
|
||||
H264PictureInfo info = pictureInfo.Convert();
|
||||
|
||||
ReadOnlySpan<byte> bitstream = rm.Gmm.DeviceGetSpan(state.SetInBufBaseOffset, (int)pictureInfo.BitstreamSize);
|
||||
ReadOnlySpan<byte> bitstream = rm.MemoryManager.DeviceGetSpan(state.SetInBufBaseOffset, (int)pictureInfo.BitstreamSize);
|
||||
|
||||
int width = (int)pictureInfo.PicWidthInMbs * MbSizeInPixels;
|
||||
int height = (int)pictureInfo.PicHeightInMbs * MbSizeInPixels;
|
||||
@ -34,7 +34,7 @@ namespace Ryujinx.Graphics.Nvdec
|
||||
if (outputSurface.Field == FrameField.Progressive)
|
||||
{
|
||||
SurfaceWriter.Write(
|
||||
rm.Gmm,
|
||||
rm.MemoryManager,
|
||||
outputSurface,
|
||||
lumaOffset + pictureInfo.LumaFrameOffset,
|
||||
chromaOffset + pictureInfo.ChromaFrameOffset);
|
||||
@ -42,7 +42,7 @@ namespace Ryujinx.Graphics.Nvdec
|
||||
else
|
||||
{
|
||||
SurfaceWriter.WriteInterlaced(
|
||||
rm.Gmm,
|
||||
rm.MemoryManager,
|
||||
outputSurface,
|
||||
lumaOffset + pictureInfo.LumaTopFieldOffset,
|
||||
chromaOffset + pictureInfo.ChromaTopFieldOffset,
|
||||
|
@ -1,4 +1,4 @@
|
||||
using Ryujinx.Graphics.Gpu.Memory;
|
||||
using Ryujinx.Graphics.Device;
|
||||
using Ryujinx.Graphics.Video;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
@ -27,11 +27,11 @@ namespace Ryujinx.Graphics.Nvdec.Image
|
||||
|
||||
private readonly CacheItem[] _pool = new CacheItem[MaxItems];
|
||||
|
||||
private readonly MemoryManager _gmm;
|
||||
private readonly DeviceMemoryManager _mm;
|
||||
|
||||
public SurfaceCache(MemoryManager gmm)
|
||||
public SurfaceCache(DeviceMemoryManager mm)
|
||||
{
|
||||
_gmm = gmm;
|
||||
_mm = mm;
|
||||
}
|
||||
|
||||
public ISurface Get(IDecoder decoder, uint lumaOffset, uint chromaOffset, int width, int height)
|
||||
@ -77,7 +77,7 @@ namespace Ryujinx.Graphics.Nvdec.Image
|
||||
|
||||
if ((lumaOffset | chromaOffset) != 0)
|
||||
{
|
||||
SurfaceReader.Read(_gmm, surface, lumaOffset, chromaOffset);
|
||||
SurfaceReader.Read(_mm, surface, lumaOffset, chromaOffset);
|
||||
}
|
||||
|
||||
MoveToFront(i);
|
||||
@ -100,7 +100,7 @@ namespace Ryujinx.Graphics.Nvdec.Image
|
||||
|
||||
if ((lumaOffset | chromaOffset) != 0)
|
||||
{
|
||||
SurfaceReader.Read(_gmm, surface, lumaOffset, chromaOffset);
|
||||
SurfaceReader.Read(_mm, surface, lumaOffset, chromaOffset);
|
||||
}
|
||||
|
||||
MoveToFront(MaxItems - 1);
|
||||
|
@ -1,5 +1,5 @@
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Graphics.Gpu.Memory;
|
||||
using Ryujinx.Graphics.Device;
|
||||
using Ryujinx.Graphics.Texture;
|
||||
using Ryujinx.Graphics.Video;
|
||||
using System;
|
||||
@ -11,13 +11,13 @@ namespace Ryujinx.Graphics.Nvdec.Image
|
||||
{
|
||||
static class SurfaceReader
|
||||
{
|
||||
public static void Read(MemoryManager gmm, ISurface surface, uint lumaOffset, uint chromaOffset)
|
||||
public static void Read(DeviceMemoryManager mm, ISurface surface, uint lumaOffset, uint chromaOffset)
|
||||
{
|
||||
int width = surface.Width;
|
||||
int height = surface.Height;
|
||||
int stride = surface.Stride;
|
||||
|
||||
ReadOnlySpan<byte> luma = gmm.DeviceGetSpan(lumaOffset, GetBlockLinearSize(width, height, 1));
|
||||
ReadOnlySpan<byte> luma = mm.DeviceGetSpan(lumaOffset, GetBlockLinearSize(width, height, 1));
|
||||
|
||||
ReadLuma(surface.YPlane.AsSpan(), luma, stride, width, height);
|
||||
|
||||
@ -25,7 +25,7 @@ namespace Ryujinx.Graphics.Nvdec.Image
|
||||
int uvHeight = surface.UvHeight;
|
||||
int uvStride = surface.UvStride;
|
||||
|
||||
ReadOnlySpan<byte> chroma = gmm.DeviceGetSpan(chromaOffset, GetBlockLinearSize(uvWidth, uvHeight, 2));
|
||||
ReadOnlySpan<byte> chroma = mm.DeviceGetSpan(chromaOffset, GetBlockLinearSize(uvWidth, uvHeight, 2));
|
||||
|
||||
ReadChroma(surface.UPlane.AsSpan(), surface.VPlane.AsSpan(), chroma, uvStride, uvWidth, uvHeight);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Graphics.Gpu.Memory;
|
||||
using Ryujinx.Graphics.Device;
|
||||
using Ryujinx.Graphics.Texture;
|
||||
using Ryujinx.Graphics.Video;
|
||||
using System;
|
||||
@ -12,11 +12,11 @@ namespace Ryujinx.Graphics.Nvdec.Image
|
||||
{
|
||||
static class SurfaceWriter
|
||||
{
|
||||
public static void Write(MemoryManager gmm, ISurface surface, uint lumaOffset, uint chromaOffset)
|
||||
public static void Write(DeviceMemoryManager mm, ISurface surface, uint lumaOffset, uint chromaOffset)
|
||||
{
|
||||
int lumaSize = GetBlockLinearSize(surface.Width, surface.Height, 1);
|
||||
|
||||
using var luma = gmm.GetWritableRegion(ExtendOffset(lumaOffset), lumaSize);
|
||||
using var luma = mm.GetWritableRegion(ExtendOffset(lumaOffset), lumaSize);
|
||||
|
||||
WriteLuma(
|
||||
luma.Memory.Span,
|
||||
@ -27,7 +27,7 @@ namespace Ryujinx.Graphics.Nvdec.Image
|
||||
|
||||
int chromaSize = GetBlockLinearSize(surface.UvWidth, surface.UvHeight, 2);
|
||||
|
||||
using var chroma = gmm.GetWritableRegion(ExtendOffset(chromaOffset), chromaSize);
|
||||
using var chroma = mm.GetWritableRegion(ExtendOffset(chromaOffset), chromaSize);
|
||||
|
||||
WriteChroma(
|
||||
chroma.Memory.Span,
|
||||
@ -39,7 +39,7 @@ namespace Ryujinx.Graphics.Nvdec.Image
|
||||
}
|
||||
|
||||
public static void WriteInterlaced(
|
||||
MemoryManager gmm,
|
||||
DeviceMemoryManager mm,
|
||||
ISurface surface,
|
||||
uint lumaTopOffset,
|
||||
uint chromaTopOffset,
|
||||
@ -48,8 +48,8 @@ namespace Ryujinx.Graphics.Nvdec.Image
|
||||
{
|
||||
int lumaSize = GetBlockLinearSize(surface.Width, surface.Height / 2, 1);
|
||||
|
||||
using var lumaTop = gmm.GetWritableRegion(ExtendOffset(lumaTopOffset), lumaSize);
|
||||
using var lumaBottom = gmm.GetWritableRegion(ExtendOffset(lumaBottomOffset), lumaSize);
|
||||
using var lumaTop = mm.GetWritableRegion(ExtendOffset(lumaTopOffset), lumaSize);
|
||||
using var lumaBottom = mm.GetWritableRegion(ExtendOffset(lumaBottomOffset), lumaSize);
|
||||
|
||||
WriteLuma(
|
||||
lumaTop.Memory.Span,
|
||||
@ -67,8 +67,8 @@ namespace Ryujinx.Graphics.Nvdec.Image
|
||||
|
||||
int chromaSize = GetBlockLinearSize(surface.UvWidth, surface.UvHeight / 2, 2);
|
||||
|
||||
using var chromaTop = gmm.GetWritableRegion(ExtendOffset(chromaTopOffset), chromaSize);
|
||||
using var chromaBottom = gmm.GetWritableRegion(ExtendOffset(chromaBottomOffset), chromaSize);
|
||||
using var chromaTop = mm.GetWritableRegion(ExtendOffset(chromaTopOffset), chromaSize);
|
||||
using var chromaBottom = mm.GetWritableRegion(ExtendOffset(chromaBottomOffset), chromaSize);
|
||||
|
||||
WriteChroma(
|
||||
chromaTop.Memory.Span,
|
||||
|
@ -1,23 +1,23 @@
|
||||
using Ryujinx.Graphics.Gpu.Memory;
|
||||
using Ryujinx.Graphics.Device;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec
|
||||
{
|
||||
static class MemoryExtensions
|
||||
{
|
||||
public static T DeviceRead<T>(this MemoryManager gmm, uint offset) where T : unmanaged
|
||||
public static T DeviceRead<T>(this DeviceMemoryManager gmm, uint offset) where T : unmanaged
|
||||
{
|
||||
return gmm.Read<T>((ulong)offset << 8);
|
||||
return gmm.Read<T>(ExtendOffset(offset));
|
||||
}
|
||||
|
||||
public static ReadOnlySpan<byte> DeviceGetSpan(this MemoryManager gmm, uint offset, int size)
|
||||
public static ReadOnlySpan<byte> DeviceGetSpan(this DeviceMemoryManager gmm, uint offset, int size)
|
||||
{
|
||||
return gmm.GetSpan((ulong)offset << 8, size);
|
||||
return gmm.GetSpan(ExtendOffset(offset), size);
|
||||
}
|
||||
|
||||
public static void DeviceWrite(this MemoryManager gmm, uint offset, ReadOnlySpan<byte> data)
|
||||
public static void DeviceWrite(this DeviceMemoryManager gmm, uint offset, ReadOnlySpan<byte> data)
|
||||
{
|
||||
gmm.Write((ulong)offset << 8, data);
|
||||
gmm.Write(ExtendOffset(offset), data);
|
||||
}
|
||||
|
||||
public static ulong ExtendOffset(uint offset)
|
||||
|
@ -1,6 +1,5 @@
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Graphics.Device;
|
||||
using Ryujinx.Graphics.Gpu.Memory;
|
||||
using Ryujinx.Graphics.Nvdec.Image;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
@ -17,9 +16,9 @@ namespace Ryujinx.Graphics.Nvdec
|
||||
private readonly ConcurrentDictionary<long, NvdecDecoderContext> _contexts;
|
||||
private NvdecDecoderContext _currentContext;
|
||||
|
||||
public NvdecDevice(MemoryManager gmm)
|
||||
public NvdecDevice(DeviceMemoryManager mm)
|
||||
{
|
||||
_rm = new ResourceManager(gmm, new SurfaceCache(gmm));
|
||||
_rm = new ResourceManager(mm, new SurfaceCache(mm));
|
||||
_state = new DeviceState<NvdecRegisters>(new Dictionary<string, RwCallback>
|
||||
{
|
||||
{ nameof(NvdecRegisters.Execute), new RwCallback(Execute, null) },
|
||||
|
@ -1,16 +1,16 @@
|
||||
using Ryujinx.Graphics.Gpu.Memory;
|
||||
using Ryujinx.Graphics.Device;
|
||||
using Ryujinx.Graphics.Nvdec.Image;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec
|
||||
{
|
||||
readonly struct ResourceManager
|
||||
{
|
||||
public MemoryManager Gmm { get; }
|
||||
public DeviceMemoryManager MemoryManager { get; }
|
||||
public SurfaceCache Cache { get; }
|
||||
|
||||
public ResourceManager(MemoryManager gmm, SurfaceCache cache)
|
||||
public ResourceManager(DeviceMemoryManager mm, SurfaceCache cache)
|
||||
{
|
||||
Gmm = gmm;
|
||||
MemoryManager = mm;
|
||||
Cache = cache;
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,6 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Graphics.Device\Ryujinx.Graphics.Device.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Graphics.Gpu\Ryujinx.Graphics.Gpu.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Graphics.Nvdec.FFmpeg\Ryujinx.Graphics.Nvdec.FFmpeg.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Graphics.Nvdec.Vp9\Ryujinx.Graphics.Nvdec.Vp9.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Graphics.Texture\Ryujinx.Graphics.Texture.csproj" />
|
||||
|
@ -10,8 +10,8 @@ namespace Ryujinx.Graphics.Nvdec
|
||||
{
|
||||
public static void Decode(NvdecDecoderContext context, ResourceManager rm, ref NvdecRegisters state)
|
||||
{
|
||||
PictureInfo pictureInfo = rm.Gmm.DeviceRead<PictureInfo>(state.SetDrvPicSetupOffset);
|
||||
ReadOnlySpan<byte> bitstream = rm.Gmm.DeviceGetSpan(state.SetInBufBaseOffset, (int)pictureInfo.VLDBufferSize);
|
||||
PictureInfo pictureInfo = rm.MemoryManager.DeviceRead<PictureInfo>(state.SetDrvPicSetupOffset);
|
||||
ReadOnlySpan<byte> bitstream = rm.MemoryManager.DeviceGetSpan(state.SetInBufBaseOffset, (int)pictureInfo.VLDBufferSize);
|
||||
|
||||
Decoder decoder = context.GetVp8Decoder();
|
||||
|
||||
@ -24,7 +24,7 @@ namespace Ryujinx.Graphics.Nvdec
|
||||
|
||||
if (decoder.Decode(ref info, outputSurface, bitstream))
|
||||
{
|
||||
SurfaceWriter.Write(rm.Gmm, outputSurface, lumaOffset, chromaOffset);
|
||||
SurfaceWriter.Write(rm.MemoryManager, outputSurface, lumaOffset, chromaOffset);
|
||||
}
|
||||
|
||||
rm.Cache.Put(outputSurface);
|
||||
|
@ -1,5 +1,5 @@
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Graphics.Gpu.Memory;
|
||||
using Ryujinx.Graphics.Device;
|
||||
using Ryujinx.Graphics.Nvdec.Image;
|
||||
using Ryujinx.Graphics.Nvdec.Types.Vp9;
|
||||
using Ryujinx.Graphics.Nvdec.Vp9;
|
||||
@ -17,8 +17,8 @@ namespace Ryujinx.Graphics.Nvdec
|
||||
|
||||
public unsafe static void Decode(ResourceManager rm, ref NvdecRegisters state)
|
||||
{
|
||||
PictureInfo pictureInfo = rm.Gmm.DeviceRead<PictureInfo>(state.SetDrvPicSetupOffset);
|
||||
EntropyProbs entropy = rm.Gmm.DeviceRead<EntropyProbs>(state.Vp9SetProbTabBufOffset);
|
||||
PictureInfo pictureInfo = rm.MemoryManager.DeviceRead<PictureInfo>(state.SetDrvPicSetupOffset);
|
||||
EntropyProbs entropy = rm.MemoryManager.DeviceRead<EntropyProbs>(state.Vp9SetProbTabBufOffset);
|
||||
|
||||
ISurface Rent(uint lumaOffset, uint chromaOffset, FrameSize size)
|
||||
{
|
||||
@ -38,19 +38,19 @@ namespace Ryujinx.Graphics.Nvdec
|
||||
|
||||
entropy.Convert(ref info.Entropy);
|
||||
|
||||
ReadOnlySpan<byte> bitstream = rm.Gmm.DeviceGetSpan(state.SetInBufBaseOffset, (int)pictureInfo.BitstreamSize);
|
||||
ReadOnlySpan<byte> bitstream = rm.MemoryManager.DeviceGetSpan(state.SetInBufBaseOffset, (int)pictureInfo.BitstreamSize);
|
||||
|
||||
ReadOnlySpan<Vp9MvRef> mvsIn = ReadOnlySpan<Vp9MvRef>.Empty;
|
||||
|
||||
if (info.UsePrevInFindMvRefs)
|
||||
{
|
||||
mvsIn = GetMvsInput(rm.Gmm, pictureInfo.CurrentFrameSize, state.Vp9SetColMvReadBufOffset);
|
||||
mvsIn = GetMvsInput(rm.MemoryManager, pictureInfo.CurrentFrameSize, state.Vp9SetColMvReadBufOffset);
|
||||
}
|
||||
|
||||
int miCols = BitUtils.DivRoundUp(pictureInfo.CurrentFrameSize.Width, 8);
|
||||
int miRows = BitUtils.DivRoundUp(pictureInfo.CurrentFrameSize.Height, 8);
|
||||
|
||||
using var mvsRegion = rm.Gmm.GetWritableRegion(ExtendOffset(state.Vp9SetColMvWriteBufOffset), miRows * miCols * 16);
|
||||
using var mvsRegion = rm.MemoryManager.GetWritableRegion(ExtendOffset(state.Vp9SetColMvWriteBufOffset), miRows * miCols * 16);
|
||||
|
||||
Span<Vp9MvRef> mvsOut = MemoryMarshal.Cast<byte, Vp9MvRef>(mvsRegion.Memory.Span);
|
||||
|
||||
@ -59,10 +59,10 @@ namespace Ryujinx.Graphics.Nvdec
|
||||
|
||||
if (_decoder.Decode(ref info, currentSurface, bitstream, mvsIn, mvsOut))
|
||||
{
|
||||
SurfaceWriter.Write(rm.Gmm, currentSurface, lumaOffset, chromaOffset);
|
||||
SurfaceWriter.Write(rm.MemoryManager, currentSurface, lumaOffset, chromaOffset);
|
||||
}
|
||||
|
||||
WriteBackwardUpdates(rm.Gmm, state.Vp9SetCtxCounterBufOffset, ref info.BackwardUpdateCounts);
|
||||
WriteBackwardUpdates(rm.MemoryManager, state.Vp9SetCtxCounterBufOffset, ref info.BackwardUpdateCounts);
|
||||
|
||||
rm.Cache.Put(lastSurface);
|
||||
rm.Cache.Put(goldenSurface);
|
||||
@ -70,17 +70,17 @@ namespace Ryujinx.Graphics.Nvdec
|
||||
rm.Cache.Put(currentSurface);
|
||||
}
|
||||
|
||||
private static ReadOnlySpan<Vp9MvRef> GetMvsInput(MemoryManager gmm, FrameSize size, uint offset)
|
||||
private static ReadOnlySpan<Vp9MvRef> GetMvsInput(DeviceMemoryManager mm, FrameSize size, uint offset)
|
||||
{
|
||||
int miCols = BitUtils.DivRoundUp(size.Width, 8);
|
||||
int miRows = BitUtils.DivRoundUp(size.Height, 8);
|
||||
|
||||
return MemoryMarshal.Cast<byte, Vp9MvRef>(gmm.DeviceGetSpan(offset, miRows * miCols * 16));
|
||||
return MemoryMarshal.Cast<byte, Vp9MvRef>(mm.DeviceGetSpan(offset, miRows * miCols * 16));
|
||||
}
|
||||
|
||||
private static void WriteBackwardUpdates(MemoryManager gmm, uint offset, ref Vp9BackwardUpdates counts)
|
||||
private static void WriteBackwardUpdates(DeviceMemoryManager mm, uint offset, ref Vp9BackwardUpdates counts)
|
||||
{
|
||||
using var backwardUpdatesRegion = gmm.GetWritableRegion(ExtendOffset(offset), Unsafe.SizeOf<BackwardUpdates>());
|
||||
using var backwardUpdatesRegion = mm.GetWritableRegion(ExtendOffset(offset), Unsafe.SizeOf<BackwardUpdates>());
|
||||
|
||||
ref var backwardUpdates = ref MemoryMarshal.Cast<byte, BackwardUpdates>(backwardUpdatesRegion.Memory.Span)[0];
|
||||
|
||||
|
@ -454,7 +454,7 @@ namespace Ryujinx.Graphics.Vic.Image
|
||||
int srcStride = GetPitch(width, bytesPerPixel);
|
||||
int inSize = srcStride * height;
|
||||
|
||||
ReadOnlySpan<byte> src = rm.Gmm.GetSpan(ExtendOffset(offset), inSize);
|
||||
ReadOnlySpan<byte> src = rm.MemoryManager.GetSpan(ExtendOffset(offset), inSize);
|
||||
|
||||
int outSize = dstStride * height;
|
||||
int bufferIndex = rm.BufferPool.RentMinimum(outSize, out byte[] buffer);
|
||||
@ -481,7 +481,7 @@ namespace Ryujinx.Graphics.Vic.Image
|
||||
{
|
||||
int inSize = GetBlockLinearSize(width, height, bytesPerPixel, gobBlocksInY);
|
||||
|
||||
ReadOnlySpan<byte> src = rm.Gmm.GetSpan(ExtendOffset(offset), inSize);
|
||||
ReadOnlySpan<byte> src = rm.MemoryManager.GetSpan(ExtendOffset(offset), inSize);
|
||||
|
||||
int outSize = dstStride * height;
|
||||
int bufferIndex = rm.BufferPool.RentMinimum(outSize, out byte[] buffer);
|
||||
|
@ -636,7 +636,7 @@ namespace Ryujinx.Graphics.Vic.Image
|
||||
{
|
||||
if (linear)
|
||||
{
|
||||
rm.Gmm.WriteMapped(ExtendOffset(offset), src);
|
||||
rm.MemoryManager.Write(ExtendOffset(offset), src);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -659,7 +659,7 @@ namespace Ryujinx.Graphics.Vic.Image
|
||||
|
||||
LayoutConverter.ConvertLinearToBlockLinear(dst, width, height, dstStride, bytesPerPixel, gobBlocksInY, src);
|
||||
|
||||
rm.Gmm.WriteMapped(ExtendOffset(offset), dst);
|
||||
rm.MemoryManager.Write(ExtendOffset(offset), dst);
|
||||
|
||||
rm.BufferPool.Return(dstIndex);
|
||||
}
|
||||
|
@ -1,17 +1,17 @@
|
||||
using Ryujinx.Graphics.Gpu.Memory;
|
||||
using Ryujinx.Graphics.Device;
|
||||
using Ryujinx.Graphics.Vic.Image;
|
||||
|
||||
namespace Ryujinx.Graphics.Vic
|
||||
{
|
||||
readonly struct ResourceManager
|
||||
{
|
||||
public MemoryManager Gmm { get; }
|
||||
public DeviceMemoryManager MemoryManager { get; }
|
||||
public BufferPool<Pixel> SurfacePool { get; }
|
||||
public BufferPool<byte> BufferPool { get; }
|
||||
|
||||
public ResourceManager(MemoryManager gmm, BufferPool<Pixel> surfacePool, BufferPool<byte> bufferPool)
|
||||
public ResourceManager(DeviceMemoryManager mm, BufferPool<Pixel> surfacePool, BufferPool<byte> bufferPool)
|
||||
{
|
||||
Gmm = gmm;
|
||||
MemoryManager = mm;
|
||||
SurfacePool = surfacePool;
|
||||
BufferPool = bufferPool;
|
||||
}
|
||||
|
@ -8,7 +8,6 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Graphics.Device\Ryujinx.Graphics.Device.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Graphics.Gpu\Ryujinx.Graphics.Gpu.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Graphics.Host1x\Ryujinx.Graphics.Host1x.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Graphics.Texture\Ryujinx.Graphics.Texture.csproj" />
|
||||
</ItemGroup>
|
||||
|
@ -1,5 +1,4 @@
|
||||
using Ryujinx.Graphics.Device;
|
||||
using Ryujinx.Graphics.Gpu.Memory;
|
||||
using Ryujinx.Graphics.Vic.Image;
|
||||
using Ryujinx.Graphics.Vic.Types;
|
||||
using System;
|
||||
@ -9,14 +8,14 @@ namespace Ryujinx.Graphics.Vic
|
||||
{
|
||||
public class VicDevice : IDeviceState
|
||||
{
|
||||
private readonly MemoryManager _gmm;
|
||||
private readonly DeviceMemoryManager _mm;
|
||||
private readonly ResourceManager _rm;
|
||||
private readonly DeviceState<VicRegisters> _state;
|
||||
|
||||
public VicDevice(MemoryManager gmm)
|
||||
public VicDevice(DeviceMemoryManager mm)
|
||||
{
|
||||
_gmm = gmm;
|
||||
_rm = new ResourceManager(gmm, new BufferPool<Pixel>(), new BufferPool<byte>());
|
||||
_mm = mm;
|
||||
_rm = new ResourceManager(mm, new BufferPool<Pixel>(), new BufferPool<byte>());
|
||||
_state = new DeviceState<VicRegisters>(new Dictionary<string, RwCallback>
|
||||
{
|
||||
{ nameof(VicRegisters.Execute), new RwCallback(Execute, null) },
|
||||
@ -68,7 +67,7 @@ namespace Ryujinx.Graphics.Vic
|
||||
|
||||
private T ReadIndirect<T>(uint offset) where T : unmanaged
|
||||
{
|
||||
return _gmm.Read<T>((ulong)offset << 8);
|
||||
return _mm.Read<T>((ulong)offset << 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
using Ryujinx.Graphics.Gpu.Memory;
|
||||
using Ryujinx.Graphics.Device;
|
||||
using Ryujinx.Graphics.Host1x;
|
||||
using Ryujinx.Graphics.Nvdec;
|
||||
using Ryujinx.Graphics.Vic;
|
||||
@ -9,7 +9,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv
|
||||
{
|
||||
class Host1xContext : IDisposable
|
||||
{
|
||||
public MemoryManager Smmu { get; }
|
||||
public DeviceMemoryManager Smmu { get; }
|
||||
public NvMemoryAllocator MemoryAllocator { get; }
|
||||
public Host1xDevice Host1x { get; }
|
||||
|
||||
@ -17,7 +17,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv
|
||||
{
|
||||
MemoryAllocator = new NvMemoryAllocator();
|
||||
Host1x = new Host1xDevice(gpu.Synchronization);
|
||||
Smmu = gpu.CreateMemoryManager(pid);
|
||||
Smmu = gpu.CreateDeviceMemoryManager(pid);
|
||||
var nvdec = new NvdecDevice(Smmu);
|
||||
var vic = new VicDevice(Smmu);
|
||||
Host1x.RegisterDevice(ClassId.Nvdec, nvdec);
|
||||
|
@ -266,7 +266,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
size = (uint)map.Size;
|
||||
size = map.Size;
|
||||
}
|
||||
|
||||
NvInternalResult result = NvInternalResult.Success;
|
||||
|
@ -250,12 +250,12 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel
|
||||
{
|
||||
if (map.DmaMapAddress == 0)
|
||||
{
|
||||
ulong va = _host1xContext.MemoryAllocator.GetFreeAddress((ulong)map.Size, out ulong freeAddressStartPosition, 1, MemoryManager.PageSize);
|
||||
ulong va = _host1xContext.MemoryAllocator.GetFreeAddress(map.Size, out ulong freeAddressStartPosition, 1, MemoryManager.PageSize);
|
||||
|
||||
if (va != NvMemoryAllocator.PteUnmapped && va <= uint.MaxValue && (va + (uint)map.Size) <= uint.MaxValue)
|
||||
if (va != NvMemoryAllocator.PteUnmapped && va <= uint.MaxValue && (va + map.Size) <= uint.MaxValue)
|
||||
{
|
||||
_host1xContext.MemoryAllocator.AllocateRange(va, (uint)map.Size, freeAddressStartPosition);
|
||||
_host1xContext.Smmu.Map(map.Address, va, (uint)map.Size, PteKind.Pitch); // FIXME: This should not use the GMMU.
|
||||
_host1xContext.MemoryAllocator.AllocateRange(va, map.Size, freeAddressStartPosition);
|
||||
_host1xContext.Smmu.Map(map.Address, va, map.Size);
|
||||
map.DmaMapAddress = va;
|
||||
}
|
||||
else
|
||||
|
@ -69,7 +69,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
|
||||
return NvInternalResult.InvalidInput;
|
||||
}
|
||||
|
||||
int size = BitUtils.AlignUp(arguments.Size, (int)MemoryManager.PageSize);
|
||||
uint size = BitUtils.AlignUp(arguments.Size, (uint)MemoryManager.PageSize);
|
||||
|
||||
arguments.Handle = CreateHandleFromMap(new NvMapHandle(size));
|
||||
|
||||
@ -128,7 +128,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
|
||||
map.Align = arguments.Align;
|
||||
map.Kind = (byte)arguments.Kind;
|
||||
|
||||
int size = BitUtils.AlignUp(map.Size, (int)MemoryManager.PageSize);
|
||||
uint size = BitUtils.AlignUp(map.Size, (uint)MemoryManager.PageSize);
|
||||
|
||||
ulong address = arguments.Address;
|
||||
|
||||
@ -191,7 +191,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
|
||||
switch (arguments.Param)
|
||||
{
|
||||
case NvMapHandleParam.Size:
|
||||
arguments.Result = map.Size;
|
||||
arguments.Result = (int)map.Size;
|
||||
break;
|
||||
case NvMapHandleParam.Align:
|
||||
arguments.Result = map.Align;
|
||||
|
@ -5,7 +5,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct NvMapCreate
|
||||
{
|
||||
public int Size;
|
||||
public uint Size;
|
||||
public int Handle;
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
|
||||
public int Handle;
|
||||
public int Padding;
|
||||
public ulong Address;
|
||||
public int Size;
|
||||
public uint Size;
|
||||
public int Flags;
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
|
||||
public int Handle;
|
||||
public int Id;
|
||||
#pragma warning restore CS0649
|
||||
public int Size;
|
||||
public uint Size;
|
||||
public int Align;
|
||||
public int Kind;
|
||||
public ulong Address;
|
||||
@ -22,7 +22,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
|
||||
_dupes = 1;
|
||||
}
|
||||
|
||||
public NvMapHandle(int size) : this()
|
||||
public NvMapHandle(uint size) : this()
|
||||
{
|
||||
Size = size;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user