diff options
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Engine/MethodCopyBuffer.cs')
-rw-r--r-- | Ryujinx.Graphics.Gpu/Engine/MethodCopyBuffer.cs | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodCopyBuffer.cs b/Ryujinx.Graphics.Gpu/Engine/MethodCopyBuffer.cs new file mode 100644 index 00000000..19ffb0e3 --- /dev/null +++ b/Ryujinx.Graphics.Gpu/Engine/MethodCopyBuffer.cs @@ -0,0 +1,79 @@ +using Ryujinx.Graphics.Gpu.State; +using Ryujinx.Graphics.Texture; +using System; + +namespace Ryujinx.Graphics.Gpu.Engine +{ + partial class Methods + { + private void CopyBuffer(int argument) + { + var cbp = _context.State.Get<CopyBufferParams>(MethodOffset.CopyBufferParams); + + var swizzle = _context.State.Get<CopyBufferSwizzle>(MethodOffset.CopyBufferSwizzle); + + bool srcLinear = (argument & (1 << 7)) != 0; + bool dstLinear = (argument & (1 << 8)) != 0; + bool copy2D = (argument & (1 << 9)) != 0; + + int size = cbp.XCount; + + if (size == 0) + { + return; + } + + if (copy2D) + { + // Buffer to texture copy. + int srcBpp = swizzle.UnpackSrcComponentsCount() * swizzle.UnpackComponentSize(); + int dstBpp = swizzle.UnpackDstComponentsCount() * swizzle.UnpackComponentSize(); + + var dst = _context.State.Get<CopyBufferTexture>(MethodOffset.CopyBufferDstTexture); + var src = _context.State.Get<CopyBufferTexture>(MethodOffset.CopyBufferSrcTexture); + + var srcCalculator = new OffsetCalculator( + src.Width, + src.Height, + cbp.SrcStride, + srcLinear, + src.MemoryLayout.UnpackGobBlocksInY(), + srcBpp); + + var dstCalculator = new OffsetCalculator( + dst.Width, + dst.Height, + cbp.DstStride, + dstLinear, + dst.MemoryLayout.UnpackGobBlocksInY(), + dstBpp); + + ulong srcBaseAddress = _context.MemoryManager.Translate(cbp.SrcAddress.Pack()); + ulong dstBaseAddress = _context.MemoryManager.Translate(cbp.DstAddress.Pack()); + + for (int y = 0; y < cbp.YCount; y++) + for (int x = 0; x < cbp.XCount; x++) + { + int srcOffset = srcCalculator.GetOffset(src.RegionX + x, src.RegionY + y); + int dstOffset = dstCalculator.GetOffset(dst.RegionX + x, dst.RegionY + y); + + ulong srcAddress = srcBaseAddress + (ulong)srcOffset; + ulong dstAddress = dstBaseAddress + (ulong)dstOffset; + + Span<byte> pixel = _context.PhysicalMemory.Read(srcAddress, (ulong)srcBpp); + + _context.PhysicalMemory.Write(dstAddress, pixel); + } + } + else + { + // Buffer to buffer copy. + _bufferManager.CopyBuffer(cbp.SrcAddress, cbp.DstAddress, (uint)size); + + Span<byte> data = _context.MemoryAccessor.Read(cbp.SrcAddress.Pack(), (uint)size); + + _context.MemoryAccessor.Write(cbp.DstAddress.Pack(), data); + } + } + } +}
\ No newline at end of file |