diff options
Diffstat (limited to 'src/Ryujinx.Graphics.Gpu/Image')
-rw-r--r-- | src/Ryujinx.Graphics.Gpu/Image/FormatTable.cs | 30 | ||||
-rw-r--r-- | src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs | 20 | ||||
-rw-r--r-- | src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs | 2 |
3 files changed, 47 insertions, 5 deletions
diff --git a/src/Ryujinx.Graphics.Gpu/Image/FormatTable.cs b/src/Ryujinx.Graphics.Gpu/Image/FormatTable.cs index 1b517e63f..0af0725a2 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/FormatTable.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/FormatTable.cs | |||
@@ -651,9 +651,35 @@ namespace Ryujinx.Graphics.Gpu.Image | |||
651 | /// <returns>True if the format is valid, false otherwise</returns> | 651 | /// <returns>True if the format is valid, false otherwise</returns> |
652 | public static bool TryGetTextureFormat(uint encoded, bool isSrgb, out FormatInfo format) | 652 | public static bool TryGetTextureFormat(uint encoded, bool isSrgb, out FormatInfo format) |
653 | { | 653 | { |
654 | encoded |= (isSrgb ? 1u << 19 : 0u); | 654 | bool isPacked = (encoded & 0x80000000u) != 0; |
655 | if (isPacked) | ||
656 | { | ||
657 | encoded &= ~0x80000000u; | ||
658 | } | ||
655 | 659 | ||
656 | return _textureFormats.TryGetValue((TextureFormat)encoded, out format); | 660 | encoded |= isSrgb ? 1u << 19 : 0u; |
661 | |||
662 | bool found = _textureFormats.TryGetValue((TextureFormat)encoded, out format); | ||
663 | |||
664 | if (found && isPacked && !format.Format.IsDepthOrStencil()) | ||
665 | { | ||
666 | // If the packed flag is set, then the components of the pixel are tightly packed into the | ||
667 | // GPU registers on the shader. | ||
668 | // We can get the same behaviour by aliasing the texture as a format with the same amount of | ||
669 | // bytes per pixel, but only a single or the lowest possible number of components. | ||
670 | |||
671 | format = format.BytesPerPixel switch | ||
672 | { | ||
673 | 1 => new FormatInfo(Format.R8Unorm, 1, 1, 1, 1), | ||
674 | 2 => new FormatInfo(Format.R16Unorm, 1, 1, 2, 1), | ||
675 | 4 => new FormatInfo(Format.R32Float, 1, 1, 4, 1), | ||
676 | 8 => new FormatInfo(Format.R32G32Float, 1, 1, 8, 2), | ||
677 | 16 => new FormatInfo(Format.R32G32B32A32Float, 1, 1, 16, 4), | ||
678 | _ => format, | ||
679 | }; | ||
680 | } | ||
681 | |||
682 | return found; | ||
657 | } | 683 | } |
658 | 684 | ||
659 | /// <summary> | 685 | /// <summary> |
diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs index 5af0471c0..eef38948d 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs | |||
@@ -2,6 +2,8 @@ using Ryujinx.Common; | |||
2 | using Ryujinx.Graphics.GAL; | 2 | using Ryujinx.Graphics.GAL; |
3 | using Ryujinx.Graphics.Texture; | 3 | using Ryujinx.Graphics.Texture; |
4 | using System; | 4 | using System; |
5 | using System.Diagnostics; | ||
6 | using System.Numerics; | ||
5 | 7 | ||
6 | namespace Ryujinx.Graphics.Gpu.Image | 8 | namespace Ryujinx.Graphics.Gpu.Image |
7 | { | 9 | { |
@@ -339,7 +341,20 @@ namespace Ryujinx.Graphics.Gpu.Image | |||
339 | 341 | ||
340 | if (lhs.FormatInfo.BytesPerPixel != rhs.FormatInfo.BytesPerPixel && IsIncompatibleFormatAliasingAllowed(lhs.FormatInfo, rhs.FormatInfo)) | 342 | if (lhs.FormatInfo.BytesPerPixel != rhs.FormatInfo.BytesPerPixel && IsIncompatibleFormatAliasingAllowed(lhs.FormatInfo, rhs.FormatInfo)) |
341 | { | 343 | { |
342 | alignedWidthMatches = lhsSize.Width * lhs.FormatInfo.BytesPerPixel == rhsSize.Width * rhs.FormatInfo.BytesPerPixel; | 344 | // If the formats are incompatible, but the texture strides match, |
345 | // we might allow them to be copy compatible depending on the format. | ||
346 | // The strides are aligned because the format with higher bytes per pixel | ||
347 | // might need a bit of padding at the end due to one width not being a multiple of the other. | ||
348 | |||
349 | Debug.Assert((1 << BitOperations.Log2((uint)lhs.FormatInfo.BytesPerPixel)) == lhs.FormatInfo.BytesPerPixel); | ||
350 | Debug.Assert((1 << BitOperations.Log2((uint)rhs.FormatInfo.BytesPerPixel)) == rhs.FormatInfo.BytesPerPixel); | ||
351 | |||
352 | int alignment = Math.Max(lhs.FormatInfo.BytesPerPixel, rhs.FormatInfo.BytesPerPixel); | ||
353 | |||
354 | int lhsStride = BitUtils.AlignUp(lhsSize.Width * lhs.FormatInfo.BytesPerPixel, alignment); | ||
355 | int rhsStride = BitUtils.AlignUp(rhsSize.Width * rhs.FormatInfo.BytesPerPixel, alignment); | ||
356 | |||
357 | alignedWidthMatches = lhsStride == rhsStride; | ||
343 | } | 358 | } |
344 | 359 | ||
345 | TextureViewCompatibility result = TextureViewCompatibility.Full; | 360 | TextureViewCompatibility result = TextureViewCompatibility.Full; |
@@ -718,7 +733,8 @@ namespace Ryujinx.Graphics.Gpu.Image | |||
718 | (lhsFormat, rhsFormat) = (rhsFormat, lhsFormat); | 733 | (lhsFormat, rhsFormat) = (rhsFormat, lhsFormat); |
719 | } | 734 | } |
720 | 735 | ||
721 | return lhsFormat.Format == Format.R8Unorm && rhsFormat.Format == Format.R8G8B8A8Unorm; | 736 | return (lhsFormat.Format == Format.R8G8B8A8Unorm && rhsFormat.Format == Format.R32G32B32A32Float) || |
737 | (lhsFormat.Format == Format.R8Unorm && rhsFormat.Format == Format.R8G8B8A8Unorm); | ||
722 | } | 738 | } |
723 | 739 | ||
724 | /// <summary> | 740 | /// <summary> |
diff --git a/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs b/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs index 0fdb6cd64..a4035577d 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs | |||
@@ -430,7 +430,7 @@ namespace Ryujinx.Graphics.Gpu.Image | |||
430 | 430 | ||
431 | if (!FormatTable.TryGetTextureFormat(format, srgb, out FormatInfo formatInfo)) | 431 | if (!FormatTable.TryGetTextureFormat(format, srgb, out FormatInfo formatInfo)) |
432 | { | 432 | { |
433 | if (gpuVa != 0 && (int)format > 0) | 433 | if (gpuVa != 0 && format != 0) |
434 | { | 434 | { |
435 | Logger.Error?.Print(LogClass.Gpu, $"Invalid texture format 0x{format:X} (sRGB: {srgb})."); | 435 | Logger.Error?.Print(LogClass.Gpu, $"Invalid texture format 0x{format:X} (sRGB: {srgb})."); |
436 | } | 436 | } |