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
33 changed files with 555 additions and 157 deletions
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>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Ryujinx.Memory\Ryujinx.Memory.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
|
using Ryujinx.Graphics.Device;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using Ryujinx.Graphics.Gpu.Engine.GPFifo;
|
using Ryujinx.Graphics.Gpu.Engine.GPFifo;
|
||||||
using Ryujinx.Graphics.Gpu.Memory;
|
using Ryujinx.Graphics.Gpu.Memory;
|
||||||
|
@ -163,6 +164,22 @@ namespace Ryujinx.Graphics.Gpu
|
||||||
return new MemoryManager(physicalMemory);
|
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>
|
/// <summary>
|
||||||
/// Registers virtual memory used by a process for GPU memory access, caching and read/write tracking.
|
/// Registers virtual memory used by a process for GPU memory access, caching and read/write tracking.
|
||||||
/// </summary>
|
/// </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>
|
/// <summary>
|
||||||
/// Runs remap actions that are added to an unmap event.
|
/// Runs remap actions that are added to an unmap event.
|
||||||
/// These must run after the mapping completes.
|
/// These must run after the mapping completes.
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using Ryujinx.Cpu;
|
using Ryujinx.Cpu;
|
||||||
|
using Ryujinx.Graphics.Device;
|
||||||
using Ryujinx.Graphics.Gpu.Image;
|
using Ryujinx.Graphics.Gpu.Image;
|
||||||
using Ryujinx.Graphics.Gpu.Shader;
|
using Ryujinx.Graphics.Gpu.Shader;
|
||||||
using Ryujinx.Memory;
|
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>
|
/// <summary>
|
||||||
/// Gets a host pointer for a given range of application memory.
|
/// 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.
|
/// If the memory region is not a single contiguous block, this method returns 0.
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
|
using Ryujinx.Graphics.Device;
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
|
@ -7,7 +8,7 @@ namespace Ryujinx.Graphics.Gpu.Synchronization
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// GPU synchronization manager.
|
/// GPU synchronization manager.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SynchronizationManager
|
public class SynchronizationManager : ISynchronizationManager
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The maximum number of syncpoints supported by the GM20B.
|
/// The maximum number of syncpoints supported by the GM20B.
|
||||||
|
@ -29,12 +30,7 @@ namespace Ryujinx.Graphics.Gpu.Synchronization
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc/>
|
||||||
/// 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>
|
|
||||||
public uint IncrementSyncpoint(uint id)
|
public uint IncrementSyncpoint(uint id)
|
||||||
{
|
{
|
||||||
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(id, (uint)MaxHardwareSyncpoints);
|
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(id, (uint)MaxHardwareSyncpoints);
|
||||||
|
@ -42,12 +38,7 @@ namespace Ryujinx.Graphics.Gpu.Synchronization
|
||||||
return _syncpoints[id].Increment();
|
return _syncpoints[id].Increment();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc/>
|
||||||
/// 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>
|
|
||||||
public uint GetSyncpointValue(uint id)
|
public uint GetSyncpointValue(uint id)
|
||||||
{
|
{
|
||||||
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(id, (uint)MaxHardwareSyncpoints);
|
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(id, (uint)MaxHardwareSyncpoints);
|
||||||
|
@ -84,15 +75,7 @@ namespace Ryujinx.Graphics.Gpu.Synchronization
|
||||||
_syncpoints[id].UnregisterCallback(waiterInformation);
|
_syncpoints[id].UnregisterCallback(waiterInformation);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc/>
|
||||||
/// 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>
|
|
||||||
public bool WaitOnSyncpoint(uint id, uint threshold, TimeSpan timeout)
|
public bool WaitOnSyncpoint(uint id, uint threshold, TimeSpan timeout)
|
||||||
{
|
{
|
||||||
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(id, (uint)MaxHardwareSyncpoints);
|
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(id, (uint)MaxHardwareSyncpoints);
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using Ryujinx.Graphics.Device;
|
using Ryujinx.Graphics.Device;
|
||||||
using Ryujinx.Graphics.Gpu.Synchronization;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
|
@ -7,10 +6,10 @@ namespace Ryujinx.Graphics.Host1x
|
||||||
{
|
{
|
||||||
public class Host1xClass : IDeviceState
|
public class Host1xClass : IDeviceState
|
||||||
{
|
{
|
||||||
private readonly SynchronizationManager _syncMgr;
|
private readonly ISynchronizationManager _syncMgr;
|
||||||
private readonly DeviceState<Host1xClassRegisters> _state;
|
private readonly DeviceState<Host1xClassRegisters> _state;
|
||||||
|
|
||||||
public Host1xClass(SynchronizationManager syncMgr)
|
public Host1xClass(ISynchronizationManager syncMgr)
|
||||||
{
|
{
|
||||||
_syncMgr = syncMgr;
|
_syncMgr = syncMgr;
|
||||||
_state = new DeviceState<Host1xClassRegisters>(new Dictionary<string, RwCallback>
|
_state = new DeviceState<Host1xClassRegisters>(new Dictionary<string, RwCallback>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Graphics.Device;
|
using Ryujinx.Graphics.Device;
|
||||||
using Ryujinx.Graphics.Gpu.Synchronization;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
|
@ -35,7 +34,7 @@ namespace Ryujinx.Graphics.Host1x
|
||||||
private int _mask;
|
private int _mask;
|
||||||
private bool _incrementing;
|
private bool _incrementing;
|
||||||
|
|
||||||
public Host1xDevice(SynchronizationManager syncMgr)
|
public Host1xDevice(ISynchronizationManager syncMgr)
|
||||||
{
|
{
|
||||||
_syncptIncrMgr = new SyncptIncrManager(syncMgr);
|
_syncptIncrMgr = new SyncptIncrManager(syncMgr);
|
||||||
_commandQueue = new AsyncWorkQueue<Command>(Process, "Ryujinx.Host1xProcessor");
|
_commandQueue = new AsyncWorkQueue<Command>(Process, "Ryujinx.Host1xProcessor");
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Ryujinx.Graphics.Device\Ryujinx.Graphics.Device.csproj" />
|
<ProjectReference Include="..\Ryujinx.Graphics.Device\Ryujinx.Graphics.Device.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Graphics.Gpu\Ryujinx.Graphics.Gpu.csproj" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
using Ryujinx.Graphics.Gpu.Synchronization;
|
using Ryujinx.Graphics.Device;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Host1x
|
namespace Ryujinx.Graphics.Host1x
|
||||||
{
|
{
|
||||||
class SyncptIncrManager
|
class SyncptIncrManager
|
||||||
{
|
{
|
||||||
private readonly SynchronizationManager _syncMgr;
|
private readonly ISynchronizationManager _syncMgr;
|
||||||
|
|
||||||
private readonly struct SyncptIncr
|
private readonly struct SyncptIncr
|
||||||
{
|
{
|
||||||
|
@ -27,7 +27,7 @@ namespace Ryujinx.Graphics.Host1x
|
||||||
|
|
||||||
private uint _currentId;
|
private uint _currentId;
|
||||||
|
|
||||||
public SyncptIncrManager(SynchronizationManager syncMgr)
|
public SyncptIncrManager(ISynchronizationManager syncMgr)
|
||||||
{
|
{
|
||||||
_syncMgr = syncMgr;
|
_syncMgr = syncMgr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,10 +12,10 @@ namespace Ryujinx.Graphics.Nvdec
|
||||||
|
|
||||||
public static void Decode(NvdecDecoderContext context, ResourceManager rm, ref NvdecRegisters state)
|
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();
|
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 width = (int)pictureInfo.PicWidthInMbs * MbSizeInPixels;
|
||||||
int height = (int)pictureInfo.PicHeightInMbs * MbSizeInPixels;
|
int height = (int)pictureInfo.PicHeightInMbs * MbSizeInPixels;
|
||||||
|
@ -34,7 +34,7 @@ namespace Ryujinx.Graphics.Nvdec
|
||||||
if (outputSurface.Field == FrameField.Progressive)
|
if (outputSurface.Field == FrameField.Progressive)
|
||||||
{
|
{
|
||||||
SurfaceWriter.Write(
|
SurfaceWriter.Write(
|
||||||
rm.Gmm,
|
rm.MemoryManager,
|
||||||
outputSurface,
|
outputSurface,
|
||||||
lumaOffset + pictureInfo.LumaFrameOffset,
|
lumaOffset + pictureInfo.LumaFrameOffset,
|
||||||
chromaOffset + pictureInfo.ChromaFrameOffset);
|
chromaOffset + pictureInfo.ChromaFrameOffset);
|
||||||
|
@ -42,7 +42,7 @@ namespace Ryujinx.Graphics.Nvdec
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SurfaceWriter.WriteInterlaced(
|
SurfaceWriter.WriteInterlaced(
|
||||||
rm.Gmm,
|
rm.MemoryManager,
|
||||||
outputSurface,
|
outputSurface,
|
||||||
lumaOffset + pictureInfo.LumaTopFieldOffset,
|
lumaOffset + pictureInfo.LumaTopFieldOffset,
|
||||||
chromaOffset + pictureInfo.ChromaTopFieldOffset,
|
chromaOffset + pictureInfo.ChromaTopFieldOffset,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using Ryujinx.Graphics.Gpu.Memory;
|
using Ryujinx.Graphics.Device;
|
||||||
using Ryujinx.Graphics.Video;
|
using Ryujinx.Graphics.Video;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
@ -27,11 +27,11 @@ namespace Ryujinx.Graphics.Nvdec.Image
|
||||||
|
|
||||||
private readonly CacheItem[] _pool = new CacheItem[MaxItems];
|
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)
|
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)
|
if ((lumaOffset | chromaOffset) != 0)
|
||||||
{
|
{
|
||||||
SurfaceReader.Read(_gmm, surface, lumaOffset, chromaOffset);
|
SurfaceReader.Read(_mm, surface, lumaOffset, chromaOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
MoveToFront(i);
|
MoveToFront(i);
|
||||||
|
@ -100,7 +100,7 @@ namespace Ryujinx.Graphics.Nvdec.Image
|
||||||
|
|
||||||
if ((lumaOffset | chromaOffset) != 0)
|
if ((lumaOffset | chromaOffset) != 0)
|
||||||
{
|
{
|
||||||
SurfaceReader.Read(_gmm, surface, lumaOffset, chromaOffset);
|
SurfaceReader.Read(_mm, surface, lumaOffset, chromaOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
MoveToFront(MaxItems - 1);
|
MoveToFront(MaxItems - 1);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Graphics.Gpu.Memory;
|
using Ryujinx.Graphics.Device;
|
||||||
using Ryujinx.Graphics.Texture;
|
using Ryujinx.Graphics.Texture;
|
||||||
using Ryujinx.Graphics.Video;
|
using Ryujinx.Graphics.Video;
|
||||||
using System;
|
using System;
|
||||||
|
@ -11,13 +11,13 @@ namespace Ryujinx.Graphics.Nvdec.Image
|
||||||
{
|
{
|
||||||
static class SurfaceReader
|
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 width = surface.Width;
|
||||||
int height = surface.Height;
|
int height = surface.Height;
|
||||||
int stride = surface.Stride;
|
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);
|
ReadLuma(surface.YPlane.AsSpan(), luma, stride, width, height);
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ namespace Ryujinx.Graphics.Nvdec.Image
|
||||||
int uvHeight = surface.UvHeight;
|
int uvHeight = surface.UvHeight;
|
||||||
int uvStride = surface.UvStride;
|
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);
|
ReadChroma(surface.UPlane.AsSpan(), surface.VPlane.AsSpan(), chroma, uvStride, uvWidth, uvHeight);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Graphics.Gpu.Memory;
|
using Ryujinx.Graphics.Device;
|
||||||
using Ryujinx.Graphics.Texture;
|
using Ryujinx.Graphics.Texture;
|
||||||
using Ryujinx.Graphics.Video;
|
using Ryujinx.Graphics.Video;
|
||||||
using System;
|
using System;
|
||||||
|
@ -12,11 +12,11 @@ namespace Ryujinx.Graphics.Nvdec.Image
|
||||||
{
|
{
|
||||||
static class SurfaceWriter
|
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);
|
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(
|
WriteLuma(
|
||||||
luma.Memory.Span,
|
luma.Memory.Span,
|
||||||
|
@ -27,7 +27,7 @@ namespace Ryujinx.Graphics.Nvdec.Image
|
||||||
|
|
||||||
int chromaSize = GetBlockLinearSize(surface.UvWidth, surface.UvHeight, 2);
|
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(
|
WriteChroma(
|
||||||
chroma.Memory.Span,
|
chroma.Memory.Span,
|
||||||
|
@ -39,7 +39,7 @@ namespace Ryujinx.Graphics.Nvdec.Image
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void WriteInterlaced(
|
public static void WriteInterlaced(
|
||||||
MemoryManager gmm,
|
DeviceMemoryManager mm,
|
||||||
ISurface surface,
|
ISurface surface,
|
||||||
uint lumaTopOffset,
|
uint lumaTopOffset,
|
||||||
uint chromaTopOffset,
|
uint chromaTopOffset,
|
||||||
|
@ -48,8 +48,8 @@ namespace Ryujinx.Graphics.Nvdec.Image
|
||||||
{
|
{
|
||||||
int lumaSize = GetBlockLinearSize(surface.Width, surface.Height / 2, 1);
|
int lumaSize = GetBlockLinearSize(surface.Width, surface.Height / 2, 1);
|
||||||
|
|
||||||
using var lumaTop = gmm.GetWritableRegion(ExtendOffset(lumaTopOffset), lumaSize);
|
using var lumaTop = mm.GetWritableRegion(ExtendOffset(lumaTopOffset), lumaSize);
|
||||||
using var lumaBottom = gmm.GetWritableRegion(ExtendOffset(lumaBottomOffset), lumaSize);
|
using var lumaBottom = mm.GetWritableRegion(ExtendOffset(lumaBottomOffset), lumaSize);
|
||||||
|
|
||||||
WriteLuma(
|
WriteLuma(
|
||||||
lumaTop.Memory.Span,
|
lumaTop.Memory.Span,
|
||||||
|
@ -67,8 +67,8 @@ namespace Ryujinx.Graphics.Nvdec.Image
|
||||||
|
|
||||||
int chromaSize = GetBlockLinearSize(surface.UvWidth, surface.UvHeight / 2, 2);
|
int chromaSize = GetBlockLinearSize(surface.UvWidth, surface.UvHeight / 2, 2);
|
||||||
|
|
||||||
using var chromaTop = gmm.GetWritableRegion(ExtendOffset(chromaTopOffset), chromaSize);
|
using var chromaTop = mm.GetWritableRegion(ExtendOffset(chromaTopOffset), chromaSize);
|
||||||
using var chromaBottom = gmm.GetWritableRegion(ExtendOffset(chromaBottomOffset), chromaSize);
|
using var chromaBottom = mm.GetWritableRegion(ExtendOffset(chromaBottomOffset), chromaSize);
|
||||||
|
|
||||||
WriteChroma(
|
WriteChroma(
|
||||||
chromaTop.Memory.Span,
|
chromaTop.Memory.Span,
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
using Ryujinx.Graphics.Gpu.Memory;
|
using Ryujinx.Graphics.Device;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec
|
namespace Ryujinx.Graphics.Nvdec
|
||||||
{
|
{
|
||||||
static class MemoryExtensions
|
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)
|
public static ulong ExtendOffset(uint offset)
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Graphics.Device;
|
using Ryujinx.Graphics.Device;
|
||||||
using Ryujinx.Graphics.Gpu.Memory;
|
|
||||||
using Ryujinx.Graphics.Nvdec.Image;
|
using Ryujinx.Graphics.Nvdec.Image;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -17,9 +16,9 @@ namespace Ryujinx.Graphics.Nvdec
|
||||||
private readonly ConcurrentDictionary<long, NvdecDecoderContext> _contexts;
|
private readonly ConcurrentDictionary<long, NvdecDecoderContext> _contexts;
|
||||||
private NvdecDecoderContext _currentContext;
|
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>
|
_state = new DeviceState<NvdecRegisters>(new Dictionary<string, RwCallback>
|
||||||
{
|
{
|
||||||
{ nameof(NvdecRegisters.Execute), new RwCallback(Execute, null) },
|
{ 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;
|
using Ryujinx.Graphics.Nvdec.Image;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec
|
namespace Ryujinx.Graphics.Nvdec
|
||||||
{
|
{
|
||||||
readonly struct ResourceManager
|
readonly struct ResourceManager
|
||||||
{
|
{
|
||||||
public MemoryManager Gmm { get; }
|
public DeviceMemoryManager MemoryManager { get; }
|
||||||
public SurfaceCache Cache { get; }
|
public SurfaceCache Cache { get; }
|
||||||
|
|
||||||
public ResourceManager(MemoryManager gmm, SurfaceCache cache)
|
public ResourceManager(DeviceMemoryManager mm, SurfaceCache cache)
|
||||||
{
|
{
|
||||||
Gmm = gmm;
|
MemoryManager = mm;
|
||||||
Cache = cache;
|
Cache = cache;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Graphics.Device\Ryujinx.Graphics.Device.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.FFmpeg\Ryujinx.Graphics.Nvdec.FFmpeg.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Graphics.Nvdec.Vp9\Ryujinx.Graphics.Nvdec.Vp9.csproj" />
|
<ProjectReference Include="..\Ryujinx.Graphics.Nvdec.Vp9\Ryujinx.Graphics.Nvdec.Vp9.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Graphics.Texture\Ryujinx.Graphics.Texture.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)
|
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);
|
||||||
ReadOnlySpan<byte> bitstream = rm.Gmm.DeviceGetSpan(state.SetInBufBaseOffset, (int)pictureInfo.VLDBufferSize);
|
ReadOnlySpan<byte> bitstream = rm.MemoryManager.DeviceGetSpan(state.SetInBufBaseOffset, (int)pictureInfo.VLDBufferSize);
|
||||||
|
|
||||||
Decoder decoder = context.GetVp8Decoder();
|
Decoder decoder = context.GetVp8Decoder();
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ namespace Ryujinx.Graphics.Nvdec
|
||||||
|
|
||||||
if (decoder.Decode(ref info, outputSurface, bitstream))
|
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);
|
rm.Cache.Put(outputSurface);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Graphics.Gpu.Memory;
|
using Ryujinx.Graphics.Device;
|
||||||
using Ryujinx.Graphics.Nvdec.Image;
|
using Ryujinx.Graphics.Nvdec.Image;
|
||||||
using Ryujinx.Graphics.Nvdec.Types.Vp9;
|
using Ryujinx.Graphics.Nvdec.Types.Vp9;
|
||||||
using Ryujinx.Graphics.Nvdec.Vp9;
|
using Ryujinx.Graphics.Nvdec.Vp9;
|
||||||
|
@ -17,8 +17,8 @@ namespace Ryujinx.Graphics.Nvdec
|
||||||
|
|
||||||
public unsafe static void Decode(ResourceManager rm, ref NvdecRegisters state)
|
public unsafe static void Decode(ResourceManager rm, ref NvdecRegisters state)
|
||||||
{
|
{
|
||||||
PictureInfo pictureInfo = rm.Gmm.DeviceRead<PictureInfo>(state.SetDrvPicSetupOffset);
|
PictureInfo pictureInfo = rm.MemoryManager.DeviceRead<PictureInfo>(state.SetDrvPicSetupOffset);
|
||||||
EntropyProbs entropy = rm.Gmm.DeviceRead<EntropyProbs>(state.Vp9SetProbTabBufOffset);
|
EntropyProbs entropy = rm.MemoryManager.DeviceRead<EntropyProbs>(state.Vp9SetProbTabBufOffset);
|
||||||
|
|
||||||
ISurface Rent(uint lumaOffset, uint chromaOffset, FrameSize size)
|
ISurface Rent(uint lumaOffset, uint chromaOffset, FrameSize size)
|
||||||
{
|
{
|
||||||
|
@ -38,19 +38,19 @@ namespace Ryujinx.Graphics.Nvdec
|
||||||
|
|
||||||
entropy.Convert(ref info.Entropy);
|
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;
|
ReadOnlySpan<Vp9MvRef> mvsIn = ReadOnlySpan<Vp9MvRef>.Empty;
|
||||||
|
|
||||||
if (info.UsePrevInFindMvRefs)
|
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 miCols = BitUtils.DivRoundUp(pictureInfo.CurrentFrameSize.Width, 8);
|
||||||
int miRows = BitUtils.DivRoundUp(pictureInfo.CurrentFrameSize.Height, 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);
|
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))
|
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(lastSurface);
|
||||||
rm.Cache.Put(goldenSurface);
|
rm.Cache.Put(goldenSurface);
|
||||||
|
@ -70,17 +70,17 @@ namespace Ryujinx.Graphics.Nvdec
|
||||||
rm.Cache.Put(currentSurface);
|
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 miCols = BitUtils.DivRoundUp(size.Width, 8);
|
||||||
int miRows = BitUtils.DivRoundUp(size.Height, 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];
|
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 srcStride = GetPitch(width, bytesPerPixel);
|
||||||
int inSize = srcStride * height;
|
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 outSize = dstStride * height;
|
||||||
int bufferIndex = rm.BufferPool.RentMinimum(outSize, out byte[] buffer);
|
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);
|
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 outSize = dstStride * height;
|
||||||
int bufferIndex = rm.BufferPool.RentMinimum(outSize, out byte[] buffer);
|
int bufferIndex = rm.BufferPool.RentMinimum(outSize, out byte[] buffer);
|
||||||
|
|
|
@ -636,7 +636,7 @@ namespace Ryujinx.Graphics.Vic.Image
|
||||||
{
|
{
|
||||||
if (linear)
|
if (linear)
|
||||||
{
|
{
|
||||||
rm.Gmm.WriteMapped(ExtendOffset(offset), src);
|
rm.MemoryManager.Write(ExtendOffset(offset), src);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -659,7 +659,7 @@ namespace Ryujinx.Graphics.Vic.Image
|
||||||
|
|
||||||
LayoutConverter.ConvertLinearToBlockLinear(dst, width, height, dstStride, bytesPerPixel, gobBlocksInY, src);
|
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);
|
rm.BufferPool.Return(dstIndex);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
using Ryujinx.Graphics.Gpu.Memory;
|
using Ryujinx.Graphics.Device;
|
||||||
using Ryujinx.Graphics.Vic.Image;
|
using Ryujinx.Graphics.Vic.Image;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Vic
|
namespace Ryujinx.Graphics.Vic
|
||||||
{
|
{
|
||||||
readonly struct ResourceManager
|
readonly struct ResourceManager
|
||||||
{
|
{
|
||||||
public MemoryManager Gmm { get; }
|
public DeviceMemoryManager MemoryManager { get; }
|
||||||
public BufferPool<Pixel> SurfacePool { get; }
|
public BufferPool<Pixel> SurfacePool { get; }
|
||||||
public BufferPool<byte> BufferPool { 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;
|
SurfacePool = surfacePool;
|
||||||
BufferPool = bufferPool;
|
BufferPool = bufferPool;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Graphics.Device\Ryujinx.Graphics.Device.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.Host1x\Ryujinx.Graphics.Host1x.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Graphics.Texture\Ryujinx.Graphics.Texture.csproj" />
|
<ProjectReference Include="..\Ryujinx.Graphics.Texture\Ryujinx.Graphics.Texture.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using Ryujinx.Graphics.Device;
|
using Ryujinx.Graphics.Device;
|
||||||
using Ryujinx.Graphics.Gpu.Memory;
|
|
||||||
using Ryujinx.Graphics.Vic.Image;
|
using Ryujinx.Graphics.Vic.Image;
|
||||||
using Ryujinx.Graphics.Vic.Types;
|
using Ryujinx.Graphics.Vic.Types;
|
||||||
using System;
|
using System;
|
||||||
|
@ -9,14 +8,14 @@ namespace Ryujinx.Graphics.Vic
|
||||||
{
|
{
|
||||||
public class VicDevice : IDeviceState
|
public class VicDevice : IDeviceState
|
||||||
{
|
{
|
||||||
private readonly MemoryManager _gmm;
|
private readonly DeviceMemoryManager _mm;
|
||||||
private readonly ResourceManager _rm;
|
private readonly ResourceManager _rm;
|
||||||
private readonly DeviceState<VicRegisters> _state;
|
private readonly DeviceState<VicRegisters> _state;
|
||||||
|
|
||||||
public VicDevice(MemoryManager gmm)
|
public VicDevice(DeviceMemoryManager mm)
|
||||||
{
|
{
|
||||||
_gmm = gmm;
|
_mm = mm;
|
||||||
_rm = new ResourceManager(gmm, new BufferPool<Pixel>(), new BufferPool<byte>());
|
_rm = new ResourceManager(mm, new BufferPool<Pixel>(), new BufferPool<byte>());
|
||||||
_state = new DeviceState<VicRegisters>(new Dictionary<string, RwCallback>
|
_state = new DeviceState<VicRegisters>(new Dictionary<string, RwCallback>
|
||||||
{
|
{
|
||||||
{ nameof(VicRegisters.Execute), new RwCallback(Execute, null) },
|
{ nameof(VicRegisters.Execute), new RwCallback(Execute, null) },
|
||||||
|
@ -68,7 +67,7 @@ namespace Ryujinx.Graphics.Vic
|
||||||
|
|
||||||
private T ReadIndirect<T>(uint offset) where T : unmanaged
|
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.Host1x;
|
||||||
using Ryujinx.Graphics.Nvdec;
|
using Ryujinx.Graphics.Nvdec;
|
||||||
using Ryujinx.Graphics.Vic;
|
using Ryujinx.Graphics.Vic;
|
||||||
|
@ -9,7 +9,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv
|
||||||
{
|
{
|
||||||
class Host1xContext : IDisposable
|
class Host1xContext : IDisposable
|
||||||
{
|
{
|
||||||
public MemoryManager Smmu { get; }
|
public DeviceMemoryManager Smmu { get; }
|
||||||
public NvMemoryAllocator MemoryAllocator { get; }
|
public NvMemoryAllocator MemoryAllocator { get; }
|
||||||
public Host1xDevice Host1x { get; }
|
public Host1xDevice Host1x { get; }
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv
|
||||||
{
|
{
|
||||||
MemoryAllocator = new NvMemoryAllocator();
|
MemoryAllocator = new NvMemoryAllocator();
|
||||||
Host1x = new Host1xDevice(gpu.Synchronization);
|
Host1x = new Host1xDevice(gpu.Synchronization);
|
||||||
Smmu = gpu.CreateMemoryManager(pid);
|
Smmu = gpu.CreateDeviceMemoryManager(pid);
|
||||||
var nvdec = new NvdecDevice(Smmu);
|
var nvdec = new NvdecDevice(Smmu);
|
||||||
var vic = new VicDevice(Smmu);
|
var vic = new VicDevice(Smmu);
|
||||||
Host1x.RegisterDevice(ClassId.Nvdec, nvdec);
|
Host1x.RegisterDevice(ClassId.Nvdec, nvdec);
|
||||||
|
|
|
@ -266,7 +266,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu
|
||||||
|
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
{
|
{
|
||||||
size = (uint)map.Size;
|
size = map.Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
NvInternalResult result = NvInternalResult.Success;
|
NvInternalResult result = NvInternalResult.Success;
|
||||||
|
|
|
@ -250,12 +250,12 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostChannel
|
||||||
{
|
{
|
||||||
if (map.DmaMapAddress == 0)
|
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.MemoryAllocator.AllocateRange(va, map.Size, freeAddressStartPosition);
|
||||||
_host1xContext.Smmu.Map(map.Address, va, (uint)map.Size, PteKind.Pitch); // FIXME: This should not use the GMMU.
|
_host1xContext.Smmu.Map(map.Address, va, map.Size);
|
||||||
map.DmaMapAddress = va;
|
map.DmaMapAddress = va;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -69,7 +69,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
|
||||||
return NvInternalResult.InvalidInput;
|
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));
|
arguments.Handle = CreateHandleFromMap(new NvMapHandle(size));
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
|
||||||
map.Align = arguments.Align;
|
map.Align = arguments.Align;
|
||||||
map.Kind = (byte)arguments.Kind;
|
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;
|
ulong address = arguments.Address;
|
||||||
|
|
||||||
|
@ -191,7 +191,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
|
||||||
switch (arguments.Param)
|
switch (arguments.Param)
|
||||||
{
|
{
|
||||||
case NvMapHandleParam.Size:
|
case NvMapHandleParam.Size:
|
||||||
arguments.Result = map.Size;
|
arguments.Result = (int)map.Size;
|
||||||
break;
|
break;
|
||||||
case NvMapHandleParam.Align:
|
case NvMapHandleParam.Align:
|
||||||
arguments.Result = map.Align;
|
arguments.Result = map.Align;
|
||||||
|
|
|
@ -5,7 +5,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
struct NvMapCreate
|
struct NvMapCreate
|
||||||
{
|
{
|
||||||
public int Size;
|
public uint Size;
|
||||||
public int Handle;
|
public int Handle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
|
||||||
public int Handle;
|
public int Handle;
|
||||||
public int Padding;
|
public int Padding;
|
||||||
public ulong Address;
|
public ulong Address;
|
||||||
public int Size;
|
public uint Size;
|
||||||
public int Flags;
|
public int Flags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
|
||||||
public int Handle;
|
public int Handle;
|
||||||
public int Id;
|
public int Id;
|
||||||
#pragma warning restore CS0649
|
#pragma warning restore CS0649
|
||||||
public int Size;
|
public uint Size;
|
||||||
public int Align;
|
public int Align;
|
||||||
public int Kind;
|
public int Kind;
|
||||||
public ulong Address;
|
public ulong Address;
|
||||||
|
@ -22,7 +22,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
|
||||||
_dupes = 1;
|
_dupes = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NvMapHandle(int size) : this()
|
public NvMapHandle(uint size) : this()
|
||||||
{
|
{
|
||||||
Size = size;
|
Size = size;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue