aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Gpu/Engine/Dma
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2024-09-15 18:12:05 -0300
committerGitHub <noreply@github.com>2024-09-15 18:12:05 -0300
commitcd74ae1bbd491987d983bfff36545451e2e6764c (patch)
treee4a3156c29f49497d39d2048a66d71ee91e01430 /src/Ryujinx.Graphics.Gpu/Engine/Dma
parent62216782ca9ca12ea01c88b2a43733e8949c5692 (diff)
Implement fast DMA texture to texture copy (#7299)
* Implement fast DMA texture to texture copy * PR feedback
Diffstat (limited to 'src/Ryujinx.Graphics.Gpu/Engine/Dma')
-rw-r--r--src/Ryujinx.Graphics.Gpu/Engine/Dma/DmaClass.cs48
1 files changed, 46 insertions, 2 deletions
diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Dma/DmaClass.cs b/src/Ryujinx.Graphics.Gpu/Engine/Dma/DmaClass.cs
index 218db15c..f2bfd8ea 100644
--- a/src/Ryujinx.Graphics.Gpu/Engine/Dma/DmaClass.cs
+++ b/src/Ryujinx.Graphics.Gpu/Engine/Dma/DmaClass.cs
@@ -276,8 +276,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
dstBaseOffset += dstStride * (yCount - 1);
}
- ReadOnlySpan<byte> srcSpan = memoryManager.GetSpan(srcGpuVa + (ulong)srcBaseOffset, srcSize, true);
-
// If remapping is disabled, we always copy the components directly, in order.
// If it's enabled, but the mapping is just XYZW, we also copy them in order.
bool isIdentityRemap = !remap ||
@@ -289,6 +287,52 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
bool completeSource = IsTextureCopyComplete(src, srcLinear, srcBpp, srcStride, xCount, yCount);
bool completeDest = IsTextureCopyComplete(dst, dstLinear, dstBpp, dstStride, xCount, yCount);
+ // Check if the source texture exists on the GPU, if it does, do a GPU side copy.
+ // Otherwise, we would need to flush the source texture which is costly.
+ // We don't expect the source to be linear in such cases, as linear source usually indicates buffer or CPU written data.
+
+ if (completeSource && completeDest && !srcLinear && isIdentityRemap)
+ {
+ var source = memoryManager.Physical.TextureCache.FindTexture(
+ memoryManager,
+ srcGpuVa,
+ srcBpp,
+ srcStride,
+ src.Height,
+ xCount,
+ yCount,
+ srcLinear,
+ src.MemoryLayout.UnpackGobBlocksInY(),
+ src.MemoryLayout.UnpackGobBlocksInZ());
+
+ if (source != null && source.Height == yCount)
+ {
+ source.SynchronizeMemory();
+
+ var target = memoryManager.Physical.TextureCache.FindOrCreateTexture(
+ memoryManager,
+ source.Info.FormatInfo,
+ dstGpuVa,
+ xCount,
+ yCount,
+ dstStride,
+ dstLinear,
+ dst.MemoryLayout.UnpackGobBlocksInY(),
+ dst.MemoryLayout.UnpackGobBlocksInZ());
+
+ if (source.ScaleFactor != target.ScaleFactor)
+ {
+ target.PropagateScale(source);
+ }
+
+ source.HostTexture.CopyTo(target.HostTexture, 0, 0);
+ target.SignalModified();
+ return;
+ }
+ }
+
+ ReadOnlySpan<byte> srcSpan = memoryManager.GetSpan(srcGpuVa + (ulong)srcBaseOffset, srcSize, true);
+
// Try to set the texture data directly,
// but only if we are doing a complete copy,
// and not for block linear to linear copies, since those are typically accessed from the CPU.