Enable copy dependency between RGBA8 and RGBA32 formats (#5943)
* Enable copy dependency between RGBA8 and RGBA32 formats * Take packed flag into account for texture formats * Account for widths not being a multiple of each other * Don't try to alias depth textures as color, fix log condition * PR feedback
This commit is contained in:
parent
0b58f46266
commit
70d65d3d8e
3 changed files with 47 additions and 5 deletions
|
@ -651,9 +651,35 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
/// <returns>True if the format is valid, false otherwise</returns>
|
/// <returns>True if the format is valid, false otherwise</returns>
|
||||||
public static bool TryGetTextureFormat(uint encoded, bool isSrgb, out FormatInfo format)
|
public static bool TryGetTextureFormat(uint encoded, bool isSrgb, out FormatInfo format)
|
||||||
{
|
{
|
||||||
encoded |= (isSrgb ? 1u << 19 : 0u);
|
bool isPacked = (encoded & 0x80000000u) != 0;
|
||||||
|
if (isPacked)
|
||||||
|
{
|
||||||
|
encoded &= ~0x80000000u;
|
||||||
|
}
|
||||||
|
|
||||||
return _textureFormats.TryGetValue((TextureFormat)encoded, out format);
|
encoded |= isSrgb ? 1u << 19 : 0u;
|
||||||
|
|
||||||
|
bool found = _textureFormats.TryGetValue((TextureFormat)encoded, out format);
|
||||||
|
|
||||||
|
if (found && isPacked && !format.Format.IsDepthOrStencil())
|
||||||
|
{
|
||||||
|
// If the packed flag is set, then the components of the pixel are tightly packed into the
|
||||||
|
// GPU registers on the shader.
|
||||||
|
// We can get the same behaviour by aliasing the texture as a format with the same amount of
|
||||||
|
// bytes per pixel, but only a single or the lowest possible number of components.
|
||||||
|
|
||||||
|
format = format.BytesPerPixel switch
|
||||||
|
{
|
||||||
|
1 => new FormatInfo(Format.R8Unorm, 1, 1, 1, 1),
|
||||||
|
2 => new FormatInfo(Format.R16Unorm, 1, 1, 2, 1),
|
||||||
|
4 => new FormatInfo(Format.R32Float, 1, 1, 4, 1),
|
||||||
|
8 => new FormatInfo(Format.R32G32Float, 1, 1, 8, 2),
|
||||||
|
16 => new FormatInfo(Format.R32G32B32A32Float, 1, 1, 16, 4),
|
||||||
|
_ => format,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -2,6 +2,8 @@ using Ryujinx.Common;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using Ryujinx.Graphics.Texture;
|
using Ryujinx.Graphics.Texture;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gpu.Image
|
namespace Ryujinx.Graphics.Gpu.Image
|
||||||
{
|
{
|
||||||
|
@ -339,7 +341,20 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
|
|
||||||
if (lhs.FormatInfo.BytesPerPixel != rhs.FormatInfo.BytesPerPixel && IsIncompatibleFormatAliasingAllowed(lhs.FormatInfo, rhs.FormatInfo))
|
if (lhs.FormatInfo.BytesPerPixel != rhs.FormatInfo.BytesPerPixel && IsIncompatibleFormatAliasingAllowed(lhs.FormatInfo, rhs.FormatInfo))
|
||||||
{
|
{
|
||||||
alignedWidthMatches = lhsSize.Width * lhs.FormatInfo.BytesPerPixel == rhsSize.Width * rhs.FormatInfo.BytesPerPixel;
|
// If the formats are incompatible, but the texture strides match,
|
||||||
|
// we might allow them to be copy compatible depending on the format.
|
||||||
|
// The strides are aligned because the format with higher bytes per pixel
|
||||||
|
// might need a bit of padding at the end due to one width not being a multiple of the other.
|
||||||
|
|
||||||
|
Debug.Assert((1 << BitOperations.Log2((uint)lhs.FormatInfo.BytesPerPixel)) == lhs.FormatInfo.BytesPerPixel);
|
||||||
|
Debug.Assert((1 << BitOperations.Log2((uint)rhs.FormatInfo.BytesPerPixel)) == rhs.FormatInfo.BytesPerPixel);
|
||||||
|
|
||||||
|
int alignment = Math.Max(lhs.FormatInfo.BytesPerPixel, rhs.FormatInfo.BytesPerPixel);
|
||||||
|
|
||||||
|
int lhsStride = BitUtils.AlignUp(lhsSize.Width * lhs.FormatInfo.BytesPerPixel, alignment);
|
||||||
|
int rhsStride = BitUtils.AlignUp(rhsSize.Width * rhs.FormatInfo.BytesPerPixel, alignment);
|
||||||
|
|
||||||
|
alignedWidthMatches = lhsStride == rhsStride;
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureViewCompatibility result = TextureViewCompatibility.Full;
|
TextureViewCompatibility result = TextureViewCompatibility.Full;
|
||||||
|
@ -718,7 +733,8 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
(lhsFormat, rhsFormat) = (rhsFormat, lhsFormat);
|
(lhsFormat, rhsFormat) = (rhsFormat, lhsFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
return lhsFormat.Format == Format.R8Unorm && rhsFormat.Format == Format.R8G8B8A8Unorm;
|
return (lhsFormat.Format == Format.R8G8B8A8Unorm && rhsFormat.Format == Format.R32G32B32A32Float) ||
|
||||||
|
(lhsFormat.Format == Format.R8Unorm && rhsFormat.Format == Format.R8G8B8A8Unorm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -430,7 +430,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
|
|
||||||
if (!FormatTable.TryGetTextureFormat(format, srgb, out FormatInfo formatInfo))
|
if (!FormatTable.TryGetTextureFormat(format, srgb, out FormatInfo formatInfo))
|
||||||
{
|
{
|
||||||
if (gpuVa != 0 && (int)format > 0)
|
if (gpuVa != 0 && format != 0)
|
||||||
{
|
{
|
||||||
Logger.Error?.Print(LogClass.Gpu, $"Invalid texture format 0x{format:X} (sRGB: {srgb}).");
|
Logger.Error?.Print(LogClass.Gpu, $"Invalid texture format 0x{format:X} (sRGB: {srgb}).");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue