From cd74ae1bbd491987d983bfff36545451e2e6764c Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sun, 15 Sep 2024 18:12:05 -0300 Subject: Implement fast DMA texture to texture copy (#7299) * Implement fast DMA texture to texture copy * PR feedback --- src/Ryujinx.Graphics.Gpu/Engine/Dma/DmaClass.cs | 48 +++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) (limited to 'src/Ryujinx.Graphics.Gpu/Engine') 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 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 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. -- cgit v1.2.3