aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Gpu/Engine/Dma/DmaClass.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Engine/Dma/DmaClass.cs')
-rw-r--r--Ryujinx.Graphics.Gpu/Engine/Dma/DmaClass.cs88
1 files changed, 86 insertions, 2 deletions
diff --git a/Ryujinx.Graphics.Gpu/Engine/Dma/DmaClass.cs b/Ryujinx.Graphics.Gpu/Engine/Dma/DmaClass.cs
index cbd0902d..df7e55a1 100644
--- a/Ryujinx.Graphics.Gpu/Engine/Dma/DmaClass.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/Dma/DmaClass.cs
@@ -1,7 +1,7 @@
using Ryujinx.Common;
-using Ryujinx.Common.Logging;
using Ryujinx.Graphics.Device;
using Ryujinx.Graphics.Gpu.Engine.Threed;
+using Ryujinx.Graphics.Gpu.Memory;
using Ryujinx.Graphics.Texture;
using System;
using System.Collections.Generic;
@@ -330,12 +330,96 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
{
// TODO: Implement remap functionality.
// Buffer to buffer copy.
- memoryManager.Physical.BufferCache.CopyBuffer(memoryManager, srcGpuVa, dstGpuVa, size);
+
+ bool srcIsPitchKind = memoryManager.GetKind(srcGpuVa).IsPitch();
+ bool dstIsPitchKind = memoryManager.GetKind(dstGpuVa).IsPitch();
+
+ if (!srcIsPitchKind && dstIsPitchKind)
+ {
+ CopyGobBlockLinearToLinear(memoryManager, srcGpuVa, dstGpuVa, size);
+ }
+ else if (srcIsPitchKind && !dstIsPitchKind)
+ {
+ CopyGobLinearToBlockLinear(memoryManager, srcGpuVa, dstGpuVa, size);
+ }
+ else
+ {
+ memoryManager.Physical.BufferCache.CopyBuffer(memoryManager, srcGpuVa, dstGpuVa, size);
+ }
}
}
}
/// <summary>
+ /// Copies block linear data with block linear GOBs to a block linear destination with linear GOBs.
+ /// </summary>
+ /// <param name="memoryManager">GPU memory manager</param>
+ /// <param name="srcGpuVa">Source GPU virtual address</param>
+ /// <param name="dstGpuVa">Destination GPU virtual address</param>
+ /// <param name="size">Size in bytes of the copy</param>
+ private static void CopyGobBlockLinearToLinear(MemoryManager memoryManager, ulong srcGpuVa, ulong dstGpuVa, ulong size)
+ {
+ if (((srcGpuVa | dstGpuVa | size) & 0xf) == 0)
+ {
+ for (ulong offset = 0; offset < size; offset += 16)
+ {
+ Vector128<byte> data = memoryManager.Read<Vector128<byte>>(ConvertGobLinearToBlockLinearAddress(srcGpuVa + offset), true);
+ memoryManager.Write(dstGpuVa + offset, data);
+ }
+ }
+ else
+ {
+ for (ulong offset = 0; offset < size; offset++)
+ {
+ byte data = memoryManager.Read<byte>(ConvertGobLinearToBlockLinearAddress(srcGpuVa + offset), true);
+ memoryManager.Write(dstGpuVa + offset, data);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Copies block linear data with linear GOBs to a block linear destination with block linear GOBs.
+ /// </summary>
+ /// <param name="memoryManager">GPU memory manager</param>
+ /// <param name="srcGpuVa">Source GPU virtual address</param>
+ /// <param name="dstGpuVa">Destination GPU virtual address</param>
+ /// <param name="size">Size in bytes of the copy</param>
+ private static void CopyGobLinearToBlockLinear(MemoryManager memoryManager, ulong srcGpuVa, ulong dstGpuVa, ulong size)
+ {
+ if (((srcGpuVa | dstGpuVa | size) & 0xf) == 0)
+ {
+ for (ulong offset = 0; offset < size; offset += 16)
+ {
+ Vector128<byte> data = memoryManager.Read<Vector128<byte>>(srcGpuVa + offset, true);
+ memoryManager.Write(ConvertGobLinearToBlockLinearAddress(dstGpuVa + offset), data);
+ }
+ }
+ else
+ {
+ for (ulong offset = 0; offset < size; offset++)
+ {
+ byte data = memoryManager.Read<byte>(srcGpuVa + offset, true);
+ memoryManager.Write(ConvertGobLinearToBlockLinearAddress(dstGpuVa + offset), data);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Calculates the GOB block linear address from a linear address.
+ /// </summary>
+ /// <param name="address">Linear address</param>
+ /// <returns>Block linear address</returns>
+ private static ulong ConvertGobLinearToBlockLinearAddress(ulong address)
+ {
+ // y2 y1 y0 x5 x4 x3 x2 x1 x0 -> x5 y2 y1 x4 y0 x3 x2 x1 x0
+ return (address & ~0x1f0UL) |
+ ((address & 0x40) >> 2) |
+ ((address & 0x10) << 1) |
+ ((address & 0x180) >> 1) |
+ ((address & 0x20) << 3);
+ }
+
+ /// <summary>
/// Performs a buffer to buffer, or buffer to texture copy, then optionally releases a semaphore.
/// </summary>
/// <param name="argument">Method call argument</param>