Просмотр исходного кода

Account for negative strides on DMA copy (#2623)

* Account for negative strides on DMA copy

* Should account for non-zero Y
gdkchan 4 лет назад
Родитель
Сommit
ac4ec1a015

+ 21 - 4
Ryujinx.Graphics.Gpu/Engine/Dma/DmaClass.cs

@@ -76,6 +76,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
         {
             if (linear)
             {
+                // If the stride is negative, the texture has to be flipped, so
+                // the fast copy is not trivial, use the slow path.
+                if (stride <= 0)
+                {
+                    return false;
+                }
+
                 int alignWidth = Constants.StrideAlignment / bpp;
                 return tex.RegionX == 0 &&
                        tex.RegionY == 0 &&
@@ -155,8 +162,18 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
                 (int srcBaseOffset, int srcSize) = srcCalculator.GetRectangleRange(src.RegionX, src.RegionY, xCount, yCount);
                 (int dstBaseOffset, int dstSize) = dstCalculator.GetRectangleRange(dst.RegionX, dst.RegionY, xCount, yCount);
 
-                ReadOnlySpan<byte> srcSpan = memoryManager.GetSpan(srcGpuVa + (uint)srcBaseOffset, srcSize, true);
-                Span<byte> dstSpan = memoryManager.GetSpan(dstGpuVa + (uint)dstBaseOffset, dstSize).ToArray();
+                if (srcLinear && srcStride < 0)
+                {
+                    srcBaseOffset += srcStride * (yCount - 1);
+                }
+
+                if (dstLinear && dstStride < 0)
+                {
+                    dstBaseOffset += dstStride * (yCount - 1);
+                }
+
+                ReadOnlySpan<byte> srcSpan = memoryManager.GetSpan(srcGpuVa + (ulong)srcBaseOffset, srcSize, true);
+                Span<byte> dstSpan = memoryManager.GetSpan(dstGpuVa + (ulong)dstBaseOffset, dstSize).ToArray();
 
                 bool completeSource = IsTextureCopyComplete(src, srcLinear, srcBpp, srcStride, xCount, yCount);
                 bool completeDest = IsTextureCopyComplete(dst, dstLinear, dstBpp, dstStride, xCount, yCount);
@@ -214,7 +231,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
                     {
                         srcSpan.CopyTo(dstSpan); // No layout conversion has to be performed, just copy the data entirely.
 
-                        memoryManager.Write(dstGpuVa + (uint)dstBaseOffset, dstSpan);
+                        memoryManager.Write(dstGpuVa + (ulong)dstBaseOffset, dstSpan);
 
                         return;
                     }
@@ -255,7 +272,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
                     _ => throw new NotSupportedException($"Unable to copy ${srcBpp} bpp pixel format.")
                 };
 
-                memoryManager.Write(dstGpuVa + (uint)dstBaseOffset, dstSpan);
+                memoryManager.Write(dstGpuVa + (ulong)dstBaseOffset, dstSpan);
             }
             else
             {

+ 1 - 3
Ryujinx.Graphics.Gpu/Engine/InlineToMemory/InlineToMemoryClass.cs

@@ -110,10 +110,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
 
             ulong dstGpuVa = ((ulong)state.OffsetOutUpperValue << 32) | state.OffsetOut;
 
-            ulong dstBaseAddress = _channel.MemoryManager.Translate(dstGpuVa);
-
             // Trigger read tracking, to flush any managed resources in the destination region.
-            _channel.MemoryManager.Physical.GetSpan(dstBaseAddress, _size, true);
+            _channel.MemoryManager.GetSpan(dstGpuVa, _size, true);
 
             _dstGpuVa = dstGpuVa;
             _dstX = state.SetDstOriginBytesXV;

+ 1 - 1
Ryujinx.Graphics.Gpu/Image/Texture.cs

@@ -892,7 +892,7 @@ namespace Ryujinx.Graphics.Gpu.Image
                 {
                     _physicalMemory.Write(Range, GetTextureDataFromGpu(Span<byte>.Empty, true, texture));
                 }
-                else 
+                else
                 {
                     _physicalMemory.WriteUntracked(Range, GetTextureDataFromGpu(Span<byte>.Empty, false, texture));
                 }

+ 4 - 3
Ryujinx.Graphics.Texture/OffsetCalculator.cs

@@ -1,4 +1,5 @@
 using Ryujinx.Common;
+using System;
 using System.Runtime.CompilerServices;
 using static Ryujinx.Graphics.Texture.BlockLinearConstants;
 
@@ -111,9 +112,9 @@ namespace Ryujinx.Graphics.Texture
         {
             if (_isLinear)
             {
-                int start = y * _stride + x * _bytesPerPixel;
-                int end = (y + height - 1) * _stride + (x + width) * _bytesPerPixel;
-                return (start, end - start);
+                int start = y * Math.Abs(_stride) + x * _bytesPerPixel;
+                int end = (y + height - 1) * Math.Abs(_stride) + (x + width) * _bytesPerPixel;
+                return (y * _stride + x * _bytesPerPixel, end - start);
             }
             else
             {