mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2025-02-19 07:43:35 +00:00
Fix BCn 4/5 conversion, GetTextureTarget
BCn 4/5 could generate invalid data when a line's size in bytes was not divisible by 4, which both backends expect. GetTextureTarget was not creating a view with the replacement format.
This commit is contained in:
parent
782a0c4e93
commit
6ba93addf7
2 changed files with 30 additions and 18 deletions
|
@ -1229,16 +1229,18 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
|
||||
if (_arrayViewTexture == null && IsSameDimensionsTarget(target))
|
||||
{
|
||||
FormatInfo formatInfo = TextureCompatibility.ToHostCompatibleFormat(Info, _context.Capabilities);
|
||||
|
||||
TextureCreateInfo createInfo = new TextureCreateInfo(
|
||||
Info.Width,
|
||||
Info.Height,
|
||||
target == Target.CubemapArray ? 6 : 1,
|
||||
Info.Levels,
|
||||
Info.Samples,
|
||||
Info.FormatInfo.BlockWidth,
|
||||
Info.FormatInfo.BlockHeight,
|
||||
Info.FormatInfo.BytesPerPixel,
|
||||
Info.FormatInfo.Format,
|
||||
formatInfo.BlockWidth,
|
||||
formatInfo.BlockHeight,
|
||||
formatInfo.BytesPerPixel,
|
||||
formatInfo.Format,
|
||||
Info.DepthStencilMode,
|
||||
target,
|
||||
Info.SwizzleR,
|
||||
|
|
|
@ -298,9 +298,12 @@ namespace Ryujinx.Graphics.Texture
|
|||
|
||||
for (int l = 0; l < levels; l++)
|
||||
{
|
||||
size += Math.Max(1, width >> l) * Math.Max(1, height >> l) * Math.Max(1, depth >> l) * layers;
|
||||
size += BitUtils.AlignUp(Math.Max(1, width >> l), 4) * Math.Max(1, height >> l) * Math.Max(1, depth >> l) * layers;
|
||||
}
|
||||
|
||||
// Backends currently expect a stride alignment of 4 bytes, so output width must be aligned.
|
||||
int alignedWidth = BitUtils.AlignUp(width, 4);
|
||||
|
||||
byte[] output = new byte[size];
|
||||
Span<byte> outputSpan = new Span<byte>(output);
|
||||
|
||||
|
@ -331,14 +334,14 @@ namespace Ryujinx.Graphics.Texture
|
|||
{
|
||||
int baseY = y * BlockHeight;
|
||||
int copyHeight = Math.Min(BlockHeight, height - baseY);
|
||||
int lineBaseOOffs = imageBaseOOffs + baseY * width;
|
||||
int lineBaseOOffs = imageBaseOOffs + baseY * alignedWidth;
|
||||
|
||||
if (copyHeight == 4)
|
||||
{
|
||||
outputLine0 = MemoryMarshal.Cast<byte, uint>(outputSpan.Slice(lineBaseOOffs));
|
||||
outputLine1 = MemoryMarshal.Cast<byte, uint>(outputSpan.Slice(lineBaseOOffs + width));
|
||||
outputLine2 = MemoryMarshal.Cast<byte, uint>(outputSpan.Slice(lineBaseOOffs + width * 2));
|
||||
outputLine3 = MemoryMarshal.Cast<byte, uint>(outputSpan.Slice(lineBaseOOffs + width * 3));
|
||||
outputLine1 = MemoryMarshal.Cast<byte, uint>(outputSpan.Slice(lineBaseOOffs + alignedWidth));
|
||||
outputLine2 = MemoryMarshal.Cast<byte, uint>(outputSpan.Slice(lineBaseOOffs + alignedWidth * 2));
|
||||
outputLine3 = MemoryMarshal.Cast<byte, uint>(outputSpan.Slice(lineBaseOOffs + alignedWidth * 3));
|
||||
}
|
||||
|
||||
for (int x = 0; x < w; x++)
|
||||
|
@ -375,7 +378,7 @@ namespace Ryujinx.Graphics.Texture
|
|||
|
||||
for (int tY = 0; tY < copyHeight; tY++)
|
||||
{
|
||||
tile.Slice(tY * 4, copyWidth).CopyTo(outputSpan.Slice(pixelBaseOOffs + width * tY, copyWidth));
|
||||
tile.Slice(tY * 4, copyWidth).CopyTo(outputSpan.Slice(pixelBaseOOffs + alignedWidth * tY, copyWidth));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -383,13 +386,15 @@ namespace Ryujinx.Graphics.Texture
|
|||
}
|
||||
}
|
||||
|
||||
imageBaseOOffs += width * height;
|
||||
imageBaseOOffs += alignedWidth * height;
|
||||
}
|
||||
}
|
||||
|
||||
width = Math.Max(1, width >> 1);
|
||||
height = Math.Max(1, height >> 1);
|
||||
depth = Math.Max(1, depth >> 1);
|
||||
|
||||
alignedWidth = BitUtils.AlignUp(width, 4);
|
||||
}
|
||||
|
||||
return output;
|
||||
|
@ -401,9 +406,12 @@ namespace Ryujinx.Graphics.Texture
|
|||
|
||||
for (int l = 0; l < levels; l++)
|
||||
{
|
||||
size += Math.Max(1, width >> l) * Math.Max(1, height >> l) * Math.Max(1, depth >> l) * layers * 2;
|
||||
size += BitUtils.AlignUp(Math.Max(1, width >> l), 2) * Math.Max(1, height >> l) * Math.Max(1, depth >> l) * layers * 2;
|
||||
}
|
||||
|
||||
// Backends currently expect a stride alignment of 4 bytes, so output width must be aligned.
|
||||
int alignedWidth = BitUtils.AlignUp(width, 2);
|
||||
|
||||
byte[] output = new byte[size];
|
||||
|
||||
ReadOnlySpan<ulong> data64 = MemoryMarshal.Cast<byte, ulong>(data);
|
||||
|
@ -438,14 +446,14 @@ namespace Ryujinx.Graphics.Texture
|
|||
{
|
||||
int baseY = y * BlockHeight;
|
||||
int copyHeight = Math.Min(BlockHeight, height - baseY);
|
||||
int lineBaseOOffs = imageBaseOOffs + baseY * width;
|
||||
int lineBaseOOffs = imageBaseOOffs + baseY * alignedWidth;
|
||||
|
||||
if (copyHeight == 4)
|
||||
{
|
||||
outputLine0 = MemoryMarshal.Cast<ushort, ulong>(outputAsUshort.Slice(lineBaseOOffs));
|
||||
outputLine1 = MemoryMarshal.Cast<ushort, ulong>(outputAsUshort.Slice(lineBaseOOffs + width));
|
||||
outputLine2 = MemoryMarshal.Cast<ushort, ulong>(outputAsUshort.Slice(lineBaseOOffs + width * 2));
|
||||
outputLine3 = MemoryMarshal.Cast<ushort, ulong>(outputAsUshort.Slice(lineBaseOOffs + width * 3));
|
||||
outputLine1 = MemoryMarshal.Cast<ushort, ulong>(outputAsUshort.Slice(lineBaseOOffs + alignedWidth));
|
||||
outputLine2 = MemoryMarshal.Cast<ushort, ulong>(outputAsUshort.Slice(lineBaseOOffs + alignedWidth * 2));
|
||||
outputLine3 = MemoryMarshal.Cast<ushort, ulong>(outputAsUshort.Slice(lineBaseOOffs + alignedWidth * 3));
|
||||
}
|
||||
|
||||
for (int x = 0; x < w; x++)
|
||||
|
@ -488,7 +496,7 @@ namespace Ryujinx.Graphics.Texture
|
|||
|
||||
for (int tY = 0; tY < copyHeight; tY++)
|
||||
{
|
||||
int line = pixelBaseOOffs + width * tY;
|
||||
int line = pixelBaseOOffs + alignedWidth * tY;
|
||||
|
||||
for (int tX = 0; tX < copyWidth; tX++)
|
||||
{
|
||||
|
@ -503,13 +511,15 @@ namespace Ryujinx.Graphics.Texture
|
|||
}
|
||||
}
|
||||
|
||||
imageBaseOOffs += width * height;
|
||||
imageBaseOOffs += alignedWidth * height;
|
||||
}
|
||||
}
|
||||
|
||||
width = Math.Max(1, width >> 1);
|
||||
height = Math.Max(1, height >> 1);
|
||||
depth = Math.Max(1, depth >> 1);
|
||||
|
||||
alignedWidth = BitUtils.AlignUp(width, 2);
|
||||
}
|
||||
|
||||
return output;
|
||||
|
|
Loading…
Reference in a new issue