Fix VIC out of bounds copy (#3386)

* Fix VIC out of bounds copy

* Update the assert
This commit is contained in:
gdkchan 2022-06-17 12:01:52 -03:00 committed by GitHub
parent 851f56b08a
commit d987cacfb7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 46 additions and 10 deletions

View file

@ -10,17 +10,22 @@ namespace Ryujinx.Graphics.Vic
{ {
static class Blender static class Blender
{ {
public static void BlendOne(Surface dst, Surface src, ref SlotStruct slot) public static void BlendOne(Surface dst, Surface src, ref SlotStruct slot, Rectangle targetRect)
{ {
if (Sse41.IsSupported && (dst.Width & 3) == 0) int x1 = targetRect.X;
int y1 = targetRect.Y;
int x2 = Math.Min(src.Width, x1 + targetRect.Width);
int y2 = Math.Min(src.Height, y1 + targetRect.Height);
if (Sse41.IsSupported && ((x1 | x2) & 3) == 0)
{ {
BlendOneSse41(dst, src, ref slot); BlendOneSse41(dst, src, ref slot, x1, y1, x2, y2);
return; return;
} }
for (int y = 0; y < dst.Height; y++) for (int y = y1; y < y2; y++)
{ {
for (int x = 0; x < dst.Width; x++) for (int x = x1; x < x2; x++)
{ {
int inR = src.GetR(x, y); int inR = src.GetR(x, y);
int inG = src.GetG(x, y); int inG = src.GetG(x, y);
@ -40,9 +45,9 @@ namespace Ryujinx.Graphics.Vic
} }
} }
private unsafe static void BlendOneSse41(Surface dst, Surface src, ref SlotStruct slot) private unsafe static void BlendOneSse41(Surface dst, Surface src, ref SlotStruct slot, int x1, int y1, int x2, int y2)
{ {
Debug.Assert((dst.Width & 3) == 0); Debug.Assert(((x1 | x2) & 3) == 0);
ref MatrixStruct mtx = ref slot.ColorMatrixStruct; ref MatrixStruct mtx = ref slot.ColorMatrixStruct;
@ -62,9 +67,9 @@ namespace Ryujinx.Graphics.Vic
Pixel* ip = srcPtr; Pixel* ip = srcPtr;
Pixel* op = dstPtr; Pixel* op = dstPtr;
for (int y = 0; y < dst.Height; y++, ip += src.Width, op += dst.Width) for (int y = y1; y < y2; y++, ip += src.Width, op += dst.Width)
{ {
for (int x = 0; x < dst.Width; x += 4) for (int x = x1; x < x2; x += 4)
{ {
Vector128<int> pixel1 = Sse41.ConvertToVector128Int32((ushort*)(ip + (uint)x)); Vector128<int> pixel1 = Sse41.ConvertToVector128Int32((ushort*)(ip + (uint)x));
Vector128<int> pixel2 = Sse41.ConvertToVector128Int32((ushort*)(ip + (uint)x + 1)); Vector128<int> pixel2 = Sse41.ConvertToVector128Int32((ushort*)(ip + (uint)x + 1));

View file

@ -0,0 +1,18 @@
namespace Ryujinx.Graphics.Vic
{
struct Rectangle
{
public readonly int X;
public readonly int Y;
public readonly int Width;
public readonly int Height;
public Rectangle(int x, int y, int width, int height)
{
X = x;
Y = y;
Width = width;
Height = height;
}
}
}

View file

@ -2,6 +2,7 @@
using Ryujinx.Graphics.Gpu.Memory; using Ryujinx.Graphics.Gpu.Memory;
using Ryujinx.Graphics.Vic.Image; using Ryujinx.Graphics.Vic.Image;
using Ryujinx.Graphics.Vic.Types; using Ryujinx.Graphics.Vic.Types;
using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Ryujinx.Graphics.Vic namespace Ryujinx.Graphics.Vic
@ -47,7 +48,19 @@ namespace Ryujinx.Graphics.Vic
using Surface src = SurfaceReader.Read(_rm, ref slot.SlotConfig, ref slot.SlotSurfaceConfig, ref offsets); using Surface src = SurfaceReader.Read(_rm, ref slot.SlotConfig, ref slot.SlotSurfaceConfig, ref offsets);
Blender.BlendOne(output, src, ref slot); int x1 = config.OutputConfig.TargetRectLeft;
int y1 = config.OutputConfig.TargetRectTop;
int x2 = config.OutputConfig.TargetRectRight + 1;
int y2 = config.OutputConfig.TargetRectBottom + 1;
int targetX = Math.Min(x1, x2);
int targetY = Math.Min(y1, y2);
int targetW = Math.Min(output.Width - targetX, Math.Abs(x2 - x1));
int targetH = Math.Min(output.Height - targetY, Math.Abs(y2 - y1));
Rectangle targetRect = new Rectangle(targetX, targetY, targetW, targetH);
Blender.BlendOne(output, src, ref slot, targetRect);
} }
SurfaceWriter.Write(_rm, output, ref config.OutputSurfaceConfig, ref _state.State.SetOutputSurface); SurfaceWriter.Write(_rm, output, ref config.OutputSurfaceConfig, ref _state.State.SetOutputSurface);