forked from Mirror/Ryujinx
Account for negative strides on DMA copy (#2623)
* Account for negative strides on DMA copy * Should account for non-zero Y
This commit is contained in:
parent
016fc64b3d
commit
ac4ec1a015
4 changed files with 27 additions and 11 deletions
|
@ -76,6 +76,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
|
||||||
{
|
{
|
||||||
if (linear)
|
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;
|
int alignWidth = Constants.StrideAlignment / bpp;
|
||||||
return tex.RegionX == 0 &&
|
return tex.RegionX == 0 &&
|
||||||
tex.RegionY == 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 srcBaseOffset, int srcSize) = srcCalculator.GetRectangleRange(src.RegionX, src.RegionY, xCount, yCount);
|
||||||
(int dstBaseOffset, int dstSize) = dstCalculator.GetRectangleRange(dst.RegionX, dst.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);
|
if (srcLinear && srcStride < 0)
|
||||||
Span<byte> dstSpan = memoryManager.GetSpan(dstGpuVa + (uint)dstBaseOffset, dstSize).ToArray();
|
{
|
||||||
|
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 completeSource = IsTextureCopyComplete(src, srcLinear, srcBpp, srcStride, xCount, yCount);
|
||||||
bool completeDest = IsTextureCopyComplete(dst, dstLinear, dstBpp, dstStride, 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.
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -255,7 +272,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
|
||||||
_ => throw new NotSupportedException($"Unable to copy ${srcBpp} bpp pixel format.")
|
_ => throw new NotSupportedException($"Unable to copy ${srcBpp} bpp pixel format.")
|
||||||
};
|
};
|
||||||
|
|
||||||
memoryManager.Write(dstGpuVa + (uint)dstBaseOffset, dstSpan);
|
memoryManager.Write(dstGpuVa + (ulong)dstBaseOffset, dstSpan);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -110,10 +110,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
|
||||||
|
|
||||||
ulong dstGpuVa = ((ulong)state.OffsetOutUpperValue << 32) | state.OffsetOut;
|
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.
|
// 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;
|
_dstGpuVa = dstGpuVa;
|
||||||
_dstX = state.SetDstOriginBytesXV;
|
_dstX = state.SetDstOriginBytesXV;
|
||||||
|
|
|
@ -892,7 +892,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
{
|
{
|
||||||
_physicalMemory.Write(Range, GetTextureDataFromGpu(Span<byte>.Empty, true, texture));
|
_physicalMemory.Write(Range, GetTextureDataFromGpu(Span<byte>.Empty, true, texture));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_physicalMemory.WriteUntracked(Range, GetTextureDataFromGpu(Span<byte>.Empty, false, texture));
|
_physicalMemory.WriteUntracked(Range, GetTextureDataFromGpu(Span<byte>.Empty, false, texture));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using static Ryujinx.Graphics.Texture.BlockLinearConstants;
|
using static Ryujinx.Graphics.Texture.BlockLinearConstants;
|
||||||
|
|
||||||
|
@ -111,9 +112,9 @@ namespace Ryujinx.Graphics.Texture
|
||||||
{
|
{
|
||||||
if (_isLinear)
|
if (_isLinear)
|
||||||
{
|
{
|
||||||
int start = y * _stride + x * _bytesPerPixel;
|
int start = y * Math.Abs(_stride) + x * _bytesPerPixel;
|
||||||
int end = (y + height - 1) * _stride + (x + width) * _bytesPerPixel;
|
int end = (y + height - 1) * Math.Abs(_stride) + (x + width) * _bytesPerPixel;
|
||||||
return (start, end - start);
|
return (y * _stride + x * _bytesPerPixel, end - start);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue