diff options
author | gdkchan <gab.dark.100@gmail.com> | 2024-09-15 18:12:05 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-15 18:12:05 -0300 |
commit | cd74ae1bbd491987d983bfff36545451e2e6764c (patch) | |
tree | e4a3156c29f49497d39d2048a66d71ee91e01430 | |
parent | 62216782ca9ca12ea01c88b2a43733e8949c5692 (diff) |
Implement fast DMA texture to texture copy (#7299)1.1.1388
* Implement fast DMA texture to texture copy
* PR feedback
-rw-r--r-- | src/Ryujinx.Graphics.Gpu/Engine/Dma/DmaClass.cs | 48 | ||||
-rw-r--r-- | src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs | 47 |
2 files changed, 93 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. diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs index b6fa842e..5a3319b0 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs @@ -351,6 +351,53 @@ namespace Ryujinx.Graphics.Gpu.Image /// Tries to find an existing texture, or create a new one if not found. /// </summary> /// <param name="memoryManager">GPU memory manager where the texture is mapped</param> + /// <param name="formatInfo">Format of the texture</param> + /// <param name="gpuAddress">GPU virtual address of the texture</param> + /// <param name="xCount">Texture width in bytes</param> + /// <param name="yCount">Texture height</param> + /// <param name="stride">Texture stride if linear, otherwise ignored</param> + /// <param name="isLinear">Indicates if the texture is linear or block linear</param> + /// <param name="gobBlocksInY">GOB blocks in Y for block linear textures</param> + /// <param name="gobBlocksInZ">GOB blocks in Z for 3D block linear textures</param> + /// <returns>The texture</returns> + public Texture FindOrCreateTexture( + MemoryManager memoryManager, + FormatInfo formatInfo, + ulong gpuAddress, + int xCount, + int yCount, + int stride, + bool isLinear, + int gobBlocksInY, + int gobBlocksInZ) + { + TextureInfo info = new( + gpuAddress, + xCount / formatInfo.BytesPerPixel, + yCount, + 1, + 1, + 1, + 1, + stride, + isLinear, + gobBlocksInY, + gobBlocksInZ, + 1, + Target.Texture2D, + formatInfo); + + Texture texture = FindOrCreateTexture(memoryManager, TextureSearchFlags.ForCopy, info, 0, sizeHint: new Size(xCount, yCount, 1)); + + texture?.SynchronizeMemory(); + + return texture; + } + + /// <summary> + /// Tries to find an existing texture, or create a new one if not found. + /// </summary> + /// <param name="memoryManager">GPU memory manager where the texture is mapped</param> /// <param name="colorState">Color buffer texture to find or create</param> /// <param name="layered">Indicates if the texture might be accessed with a non-zero layer index</param> /// <param name="discard">Indicates that the sizeHint region's data will be overwritten</param> |