forked from Mirror/Ryujinx
Fix VIC out of bounds copy (#3386)
* Fix VIC out of bounds copy * Update the assert
This commit is contained in:
parent
851f56b08a
commit
d987cacfb7
3 changed files with 46 additions and 10 deletions
|
@ -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));
|
||||||
|
|
18
Ryujinx.Graphics.Vic/Rectangle.cs
Normal file
18
Ryujinx.Graphics.Vic/Rectangle.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
Reference in a new issue