diff --git a/Ryujinx.Graphics.GAL/Format.cs b/Ryujinx.Graphics.GAL/Format.cs
index a666736141..a4e434b1f5 100644
--- a/Ryujinx.Graphics.GAL/Format.cs
+++ b/Ryujinx.Graphics.GAL/Format.cs
@@ -341,38 +341,5 @@ namespace Ryujinx.Graphics.GAL
{
return format.IsUint() || format.IsSint();
}
-
- ///
- /// Checks if the texture format only has one component.
- ///
- /// Texture format
- /// True if the texture format only has one component, false otherwise
- public static bool HasOneComponent(this Format format)
- {
- switch (format)
- {
- case Format.R8Unorm:
- case Format.R8Snorm:
- case Format.R8Uint:
- case Format.R8Sint:
- case Format.R16Float:
- case Format.R16Unorm:
- case Format.R16Snorm:
- case Format.R16Uint:
- case Format.R16Sint:
- case Format.R32Float:
- case Format.R32Uint:
- case Format.R32Sint:
- case Format.R8Uscaled:
- case Format.R8Sscaled:
- case Format.R16Uscaled:
- case Format.R16Sscaled:
- case Format.R32Uscaled:
- case Format.R32Sscaled:
- return true;
- }
-
- return false;
- }
}
}
\ No newline at end of file
diff --git a/Ryujinx.Graphics.Gpu/Image/FormatInfo.cs b/Ryujinx.Graphics.Gpu/Image/FormatInfo.cs
index 12f3aecbbd..62f41cbb02 100644
--- a/Ryujinx.Graphics.Gpu/Image/FormatInfo.cs
+++ b/Ryujinx.Graphics.Gpu/Image/FormatInfo.cs
@@ -10,7 +10,7 @@ namespace Ryujinx.Graphics.Gpu.Image
///
/// A default, generic RGBA8 texture format.
///
- public static FormatInfo Default { get; } = new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4);
+ public static FormatInfo Default { get; } = new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4, 4);
///
/// The format of the texture data.
@@ -38,6 +38,11 @@ namespace Ryujinx.Graphics.Gpu.Image
///
public int BytesPerPixel { get; }
+ ///
+ /// The maximum number of components this format has defined (in RGBA order).
+ ///
+ public int Components { get; }
+
///
/// Whenever or not the texture format is a compressed format. Determined from block size.
///
@@ -54,12 +59,14 @@ namespace Ryujinx.Graphics.Gpu.Image
Format format,
int blockWidth,
int blockHeight,
- int bytesPerPixel)
+ int bytesPerPixel,
+ int components)
{
Format = format;
BlockWidth = blockWidth;
BlockHeight = blockHeight;
BytesPerPixel = bytesPerPixel;
+ Components = components;
}
}
}
\ No newline at end of file
diff --git a/Ryujinx.Graphics.Gpu/Image/FormatTable.cs b/Ryujinx.Graphics.Gpu/Image/FormatTable.cs
index 9f8b0fa069..d8f2a9d450 100644
--- a/Ryujinx.Graphics.Gpu/Image/FormatTable.cs
+++ b/Ryujinx.Graphics.Gpu/Image/FormatTable.cs
@@ -10,102 +10,102 @@ namespace Ryujinx.Graphics.Gpu.Image
{
private static Dictionary _textureFormats = new Dictionary()
{
- { 0x2491d, new FormatInfo(Format.R8Unorm, 1, 1, 1) },
- { 0x1249d, new FormatInfo(Format.R8Snorm, 1, 1, 1) },
- { 0x4921d, new FormatInfo(Format.R8Uint, 1, 1, 1) },
- { 0x36d9d, new FormatInfo(Format.R8Sint, 1, 1, 1) },
- { 0x7ff9b, new FormatInfo(Format.R16Float, 1, 1, 2) },
- { 0x2491b, new FormatInfo(Format.R16Unorm, 1, 1, 2) },
- { 0x1249b, new FormatInfo(Format.R16Snorm, 1, 1, 2) },
- { 0x4921b, new FormatInfo(Format.R16Uint, 1, 1, 2) },
- { 0x36d9b, new FormatInfo(Format.R16Sint, 1, 1, 2) },
- { 0x7ff8f, new FormatInfo(Format.R32Float, 1, 1, 4) },
- { 0x4920f, new FormatInfo(Format.R32Uint, 1, 1, 4) },
- { 0x36d8f, new FormatInfo(Format.R32Sint, 1, 1, 4) },
- { 0x24918, new FormatInfo(Format.R8G8Unorm, 1, 1, 2) },
- { 0x12498, new FormatInfo(Format.R8G8Snorm, 1, 1, 2) },
- { 0x49218, new FormatInfo(Format.R8G8Uint, 1, 1, 2) },
- { 0x36d98, new FormatInfo(Format.R8G8Sint, 1, 1, 2) },
- { 0x7ff8c, new FormatInfo(Format.R16G16Float, 1, 1, 4) },
- { 0x2490c, new FormatInfo(Format.R16G16Unorm, 1, 1, 4) },
- { 0x1248c, new FormatInfo(Format.R16G16Snorm, 1, 1, 4) },
- { 0x4920c, new FormatInfo(Format.R16G16Uint, 1, 1, 4) },
- { 0x36d8c, new FormatInfo(Format.R16G16Sint, 1, 1, 4) },
- { 0x7ff84, new FormatInfo(Format.R32G32Float, 1, 1, 8) },
- { 0x49204, new FormatInfo(Format.R32G32Uint, 1, 1, 8) },
- { 0x36d84, new FormatInfo(Format.R32G32Sint, 1, 1, 8) },
- { 0x7ff82, new FormatInfo(Format.R32G32B32Float, 1, 1, 12) },
- { 0x49202, new FormatInfo(Format.R32G32B32Uint, 1, 1, 12) },
- { 0x36d82, new FormatInfo(Format.R32G32B32Sint, 1, 1, 12) },
- { 0x24908, new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4) },
- { 0x12488, new FormatInfo(Format.R8G8B8A8Snorm, 1, 1, 4) },
- { 0x49208, new FormatInfo(Format.R8G8B8A8Uint, 1, 1, 4) },
- { 0x36d88, new FormatInfo(Format.R8G8B8A8Sint, 1, 1, 4) },
- { 0x7ff83, new FormatInfo(Format.R16G16B16A16Float, 1, 1, 8) },
- { 0x24903, new FormatInfo(Format.R16G16B16A16Unorm, 1, 1, 8) },
- { 0x12483, new FormatInfo(Format.R16G16B16A16Snorm, 1, 1, 8) },
- { 0x49203, new FormatInfo(Format.R16G16B16A16Uint, 1, 1, 8) },
- { 0x36d83, new FormatInfo(Format.R16G16B16A16Sint, 1, 1, 8) },
- { 0x7ff81, new FormatInfo(Format.R32G32B32A32Float, 1, 1, 16) },
- { 0x49201, new FormatInfo(Format.R32G32B32A32Uint, 1, 1, 16) },
- { 0x36d81, new FormatInfo(Format.R32G32B32A32Sint, 1, 1, 16) },
- { 0x2493a, new FormatInfo(Format.D16Unorm, 1, 1, 2) },
- { 0x7ffaf, new FormatInfo(Format.D32Float, 1, 1, 4) },
- { 0x24a0e, new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4) },
- { 0x24a29, new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4) },
- { 0x25385, new FormatInfo(Format.D32FloatS8Uint, 1, 1, 8) },
- { 0x253b0, new FormatInfo(Format.D32FloatS8Uint, 1, 1, 8) },
- { 0xa4908, new FormatInfo(Format.R8G8B8A8Srgb, 1, 1, 4) },
- { 0x24912, new FormatInfo(Format.R4G4B4A4Unorm, 1, 1, 2) },
- { 0x24914, new FormatInfo(Format.R5G5B5A1Unorm, 1, 1, 2) },
- { 0x24915, new FormatInfo(Format.R5G6B5Unorm, 1, 1, 2) },
- { 0x24909, new FormatInfo(Format.R10G10B10A2Unorm, 1, 1, 4) },
- { 0x49209, new FormatInfo(Format.R10G10B10A2Uint, 1, 1, 4) },
- { 0x7ffa1, new FormatInfo(Format.R11G11B10Float, 1, 1, 4) },
- { 0x7ffa0, new FormatInfo(Format.R9G9B9E5Float, 1, 1, 4) },
- { 0x24924, new FormatInfo(Format.Bc1RgbaUnorm, 4, 4, 8) },
- { 0x24925, new FormatInfo(Format.Bc2Unorm, 4, 4, 16) },
- { 0x24926, new FormatInfo(Format.Bc3Unorm, 4, 4, 16) },
- { 0xa4924, new FormatInfo(Format.Bc1RgbaSrgb, 4, 4, 8) },
- { 0xa4925, new FormatInfo(Format.Bc2Srgb, 4, 4, 16) },
- { 0xa4926, new FormatInfo(Format.Bc3Srgb, 4, 4, 16) },
- { 0x24927, new FormatInfo(Format.Bc4Unorm, 4, 4, 8) },
- { 0x124a7, new FormatInfo(Format.Bc4Snorm, 4, 4, 8) },
- { 0x24928, new FormatInfo(Format.Bc5Unorm, 4, 4, 16) },
- { 0x124a8, new FormatInfo(Format.Bc5Snorm, 4, 4, 16) },
- { 0x24917, new FormatInfo(Format.Bc7Unorm, 4, 4, 16) },
- { 0xa4917, new FormatInfo(Format.Bc7Srgb, 4, 4, 16) },
- { 0x7ff90, new FormatInfo(Format.Bc6HSfloat, 4, 4, 16) },
- { 0x7ff91, new FormatInfo(Format.Bc6HUfloat, 4, 4, 16) },
- { 0x24940, new FormatInfo(Format.Astc4x4Unorm, 4, 4, 16) },
- { 0x24950, new FormatInfo(Format.Astc5x4Unorm, 5, 4, 16) },
- { 0x24941, new FormatInfo(Format.Astc5x5Unorm, 5, 5, 16) },
- { 0x24951, new FormatInfo(Format.Astc6x5Unorm, 6, 5, 16) },
- { 0x24942, new FormatInfo(Format.Astc6x6Unorm, 6, 6, 16) },
- { 0x24955, new FormatInfo(Format.Astc8x5Unorm, 8, 5, 16) },
- { 0x24952, new FormatInfo(Format.Astc8x6Unorm, 8, 6, 16) },
- { 0x24944, new FormatInfo(Format.Astc8x8Unorm, 8, 8, 16) },
- { 0x24956, new FormatInfo(Format.Astc10x5Unorm, 10, 5, 16) },
- { 0x24957, new FormatInfo(Format.Astc10x6Unorm, 10, 6, 16) },
- { 0x24953, new FormatInfo(Format.Astc10x8Unorm, 10, 8, 16) },
- { 0x24945, new FormatInfo(Format.Astc10x10Unorm, 10, 10, 16) },
- { 0x24954, new FormatInfo(Format.Astc12x10Unorm, 12, 10, 16) },
- { 0x24946, new FormatInfo(Format.Astc12x12Unorm, 12, 12, 16) },
- { 0xa4940, new FormatInfo(Format.Astc4x4Srgb, 4, 4, 16) },
- { 0xa4950, new FormatInfo(Format.Astc5x4Srgb, 5, 4, 16) },
- { 0xa4941, new FormatInfo(Format.Astc5x5Srgb, 5, 5, 16) },
- { 0xa4951, new FormatInfo(Format.Astc6x5Srgb, 6, 5, 16) },
- { 0xa4942, new FormatInfo(Format.Astc6x6Srgb, 6, 6, 16) },
- { 0xa4955, new FormatInfo(Format.Astc8x5Srgb, 8, 5, 16) },
- { 0xa4952, new FormatInfo(Format.Astc8x6Srgb, 8, 6, 16) },
- { 0xa4944, new FormatInfo(Format.Astc8x8Srgb, 8, 8, 16) },
- { 0xa4956, new FormatInfo(Format.Astc10x5Srgb, 10, 5, 16) },
- { 0xa4957, new FormatInfo(Format.Astc10x6Srgb, 10, 6, 16) },
- { 0xa4953, new FormatInfo(Format.Astc10x8Srgb, 10, 8, 16) },
- { 0xa4945, new FormatInfo(Format.Astc10x10Srgb, 10, 10, 16) },
- { 0xa4954, new FormatInfo(Format.Astc12x10Srgb, 12, 10, 16) },
- { 0xa4946, new FormatInfo(Format.Astc12x12Srgb, 12, 12, 16) },
- { 0x24913, new FormatInfo(Format.A1B5G5R5Unorm, 1, 1, 2) }
+ { 0x2491d, new FormatInfo(Format.R8Unorm, 1, 1, 1, 1) },
+ { 0x1249d, new FormatInfo(Format.R8Snorm, 1, 1, 1, 1) },
+ { 0x4921d, new FormatInfo(Format.R8Uint, 1, 1, 1, 1) },
+ { 0x36d9d, new FormatInfo(Format.R8Sint, 1, 1, 1, 1) },
+ { 0x7ff9b, new FormatInfo(Format.R16Float, 1, 1, 2, 1) },
+ { 0x2491b, new FormatInfo(Format.R16Unorm, 1, 1, 2, 1) },
+ { 0x1249b, new FormatInfo(Format.R16Snorm, 1, 1, 2, 1) },
+ { 0x4921b, new FormatInfo(Format.R16Uint, 1, 1, 2, 1) },
+ { 0x36d9b, new FormatInfo(Format.R16Sint, 1, 1, 2, 1) },
+ { 0x7ff8f, new FormatInfo(Format.R32Float, 1, 1, 4, 1) },
+ { 0x4920f, new FormatInfo(Format.R32Uint, 1, 1, 4, 1) },
+ { 0x36d8f, new FormatInfo(Format.R32Sint, 1, 1, 4, 1) },
+ { 0x24918, new FormatInfo(Format.R8G8Unorm, 1, 1, 2, 2) },
+ { 0x12498, new FormatInfo(Format.R8G8Snorm, 1, 1, 2, 2) },
+ { 0x49218, new FormatInfo(Format.R8G8Uint, 1, 1, 2, 2) },
+ { 0x36d98, new FormatInfo(Format.R8G8Sint, 1, 1, 2, 2) },
+ { 0x7ff8c, new FormatInfo(Format.R16G16Float, 1, 1, 4, 2) },
+ { 0x2490c, new FormatInfo(Format.R16G16Unorm, 1, 1, 4, 2) },
+ { 0x1248c, new FormatInfo(Format.R16G16Snorm, 1, 1, 4, 2) },
+ { 0x4920c, new FormatInfo(Format.R16G16Uint, 1, 1, 4, 2) },
+ { 0x36d8c, new FormatInfo(Format.R16G16Sint, 1, 1, 4, 2) },
+ { 0x7ff84, new FormatInfo(Format.R32G32Float, 1, 1, 8, 2) },
+ { 0x49204, new FormatInfo(Format.R32G32Uint, 1, 1, 8, 2) },
+ { 0x36d84, new FormatInfo(Format.R32G32Sint, 1, 1, 8, 2) },
+ { 0x7ff82, new FormatInfo(Format.R32G32B32Float, 1, 1, 12, 3) },
+ { 0x49202, new FormatInfo(Format.R32G32B32Uint, 1, 1, 12, 3) },
+ { 0x36d82, new FormatInfo(Format.R32G32B32Sint, 1, 1, 12, 3) },
+ { 0x24908, new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4, 4) },
+ { 0x12488, new FormatInfo(Format.R8G8B8A8Snorm, 1, 1, 4, 4) },
+ { 0x49208, new FormatInfo(Format.R8G8B8A8Uint, 1, 1, 4, 4) },
+ { 0x36d88, new FormatInfo(Format.R8G8B8A8Sint, 1, 1, 4, 4) },
+ { 0x7ff83, new FormatInfo(Format.R16G16B16A16Float, 1, 1, 8, 4) },
+ { 0x24903, new FormatInfo(Format.R16G16B16A16Unorm, 1, 1, 8, 4) },
+ { 0x12483, new FormatInfo(Format.R16G16B16A16Snorm, 1, 1, 8, 4) },
+ { 0x49203, new FormatInfo(Format.R16G16B16A16Uint, 1, 1, 8, 4) },
+ { 0x36d83, new FormatInfo(Format.R16G16B16A16Sint, 1, 1, 8, 4) },
+ { 0x7ff81, new FormatInfo(Format.R32G32B32A32Float, 1, 1, 16, 4) },
+ { 0x49201, new FormatInfo(Format.R32G32B32A32Uint, 1, 1, 16, 4) },
+ { 0x36d81, new FormatInfo(Format.R32G32B32A32Sint, 1, 1, 16, 4) },
+ { 0x2493a, new FormatInfo(Format.D16Unorm, 1, 1, 2, 1) },
+ { 0x7ffaf, new FormatInfo(Format.D32Float, 1, 1, 4, 1) },
+ { 0x24a0e, new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4, 2) },
+ { 0x24a29, new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4, 2) },
+ { 0x25385, new FormatInfo(Format.D32FloatS8Uint, 1, 1, 8, 2) },
+ { 0x253b0, new FormatInfo(Format.D32FloatS8Uint, 1, 1, 8, 2) },
+ { 0xa4908, new FormatInfo(Format.R8G8B8A8Srgb, 1, 1, 4, 4) },
+ { 0x24912, new FormatInfo(Format.R4G4B4A4Unorm, 1, 1, 2, 4) },
+ { 0x24914, new FormatInfo(Format.R5G5B5A1Unorm, 1, 1, 2, 4) },
+ { 0x24915, new FormatInfo(Format.R5G6B5Unorm, 1, 1, 2, 3) },
+ { 0x24909, new FormatInfo(Format.R10G10B10A2Unorm, 1, 1, 4, 4) },
+ { 0x49209, new FormatInfo(Format.R10G10B10A2Uint, 1, 1, 4, 4) },
+ { 0x7ffa1, new FormatInfo(Format.R11G11B10Float, 1, 1, 4, 3) },
+ { 0x7ffa0, new FormatInfo(Format.R9G9B9E5Float, 1, 1, 4, 4) },
+ { 0x24924, new FormatInfo(Format.Bc1RgbaUnorm, 4, 4, 8, 4) },
+ { 0x24925, new FormatInfo(Format.Bc2Unorm, 4, 4, 16, 4) },
+ { 0x24926, new FormatInfo(Format.Bc3Unorm, 4, 4, 16, 4) },
+ { 0xa4924, new FormatInfo(Format.Bc1RgbaSrgb, 4, 4, 8, 4) },
+ { 0xa4925, new FormatInfo(Format.Bc2Srgb, 4, 4, 16, 4) },
+ { 0xa4926, new FormatInfo(Format.Bc3Srgb, 4, 4, 16, 4) },
+ { 0x24927, new FormatInfo(Format.Bc4Unorm, 4, 4, 8, 1) },
+ { 0x124a7, new FormatInfo(Format.Bc4Snorm, 4, 4, 8, 1) },
+ { 0x24928, new FormatInfo(Format.Bc5Unorm, 4, 4, 16, 2) },
+ { 0x124a8, new FormatInfo(Format.Bc5Snorm, 4, 4, 16, 2) },
+ { 0x24917, new FormatInfo(Format.Bc7Unorm, 4, 4, 16, 4) },
+ { 0xa4917, new FormatInfo(Format.Bc7Srgb, 4, 4, 16, 4) },
+ { 0x7ff90, new FormatInfo(Format.Bc6HSfloat, 4, 4, 16, 4) },
+ { 0x7ff91, new FormatInfo(Format.Bc6HUfloat, 4, 4, 16, 4) },
+ { 0x24940, new FormatInfo(Format.Astc4x4Unorm, 4, 4, 16, 4) },
+ { 0x24950, new FormatInfo(Format.Astc5x4Unorm, 5, 4, 16, 4) },
+ { 0x24941, new FormatInfo(Format.Astc5x5Unorm, 5, 5, 16, 4) },
+ { 0x24951, new FormatInfo(Format.Astc6x5Unorm, 6, 5, 16, 4) },
+ { 0x24942, new FormatInfo(Format.Astc6x6Unorm, 6, 6, 16, 4) },
+ { 0x24955, new FormatInfo(Format.Astc8x5Unorm, 8, 5, 16, 4) },
+ { 0x24952, new FormatInfo(Format.Astc8x6Unorm, 8, 6, 16, 4) },
+ { 0x24944, new FormatInfo(Format.Astc8x8Unorm, 8, 8, 16, 4) },
+ { 0x24956, new FormatInfo(Format.Astc10x5Unorm, 10, 5, 16, 4) },
+ { 0x24957, new FormatInfo(Format.Astc10x6Unorm, 10, 6, 16, 4) },
+ { 0x24953, new FormatInfo(Format.Astc10x8Unorm, 10, 8, 16, 4) },
+ { 0x24945, new FormatInfo(Format.Astc10x10Unorm, 10, 10, 16, 4) },
+ { 0x24954, new FormatInfo(Format.Astc12x10Unorm, 12, 10, 16, 4) },
+ { 0x24946, new FormatInfo(Format.Astc12x12Unorm, 12, 12, 16, 4) },
+ { 0xa4940, new FormatInfo(Format.Astc4x4Srgb, 4, 4, 16, 4) },
+ { 0xa4950, new FormatInfo(Format.Astc5x4Srgb, 5, 4, 16, 4) },
+ { 0xa4941, new FormatInfo(Format.Astc5x5Srgb, 5, 5, 16, 4) },
+ { 0xa4951, new FormatInfo(Format.Astc6x5Srgb, 6, 5, 16, 4) },
+ { 0xa4942, new FormatInfo(Format.Astc6x6Srgb, 6, 6, 16, 4) },
+ { 0xa4955, new FormatInfo(Format.Astc8x5Srgb, 8, 5, 16, 4) },
+ { 0xa4952, new FormatInfo(Format.Astc8x6Srgb, 8, 6, 16, 4) },
+ { 0xa4944, new FormatInfo(Format.Astc8x8Srgb, 8, 8, 16, 4) },
+ { 0xa4956, new FormatInfo(Format.Astc10x5Srgb, 10, 5, 16, 4) },
+ { 0xa4957, new FormatInfo(Format.Astc10x6Srgb, 10, 6, 16, 4) },
+ { 0xa4953, new FormatInfo(Format.Astc10x8Srgb, 10, 8, 16, 4) },
+ { 0xa4945, new FormatInfo(Format.Astc10x10Srgb, 10, 10, 16, 4) },
+ { 0xa4954, new FormatInfo(Format.Astc12x10Srgb, 12, 10, 16, 4) },
+ { 0xa4946, new FormatInfo(Format.Astc12x12Srgb, 12, 12, 16, 4) },
+ { 0x24913, new FormatInfo(Format.A1B5G5R5Unorm, 1, 1, 2, 4) }
};
private static Dictionary _attribFormats = new Dictionary()
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs b/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs
index e8e3c2c24d..22473a1b10 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs
@@ -397,6 +397,49 @@ namespace Ryujinx.Graphics.Gpu.Image
return result ? TextureViewCompatibility.Full : TextureViewCompatibility.Incompatible;
}
+ ///
+ /// Checks if a swizzle component in two textures functionally match, taking into account if the components are defined.
+ ///
+ /// Texture information to compare
+ /// Texture information to compare with
+ /// Swizzle component for the first texture
+ /// Swizzle component for the second texture
+ /// Component index, starting at 0 for red
+ /// True if the swizzle components functionally match, false othersize
+ private static bool SwizzleComponentMatches(TextureInfo lhs, TextureInfo rhs, SwizzleComponent swizzleLhs, SwizzleComponent swizzleRhs, int component)
+ {
+ int lhsComponents = lhs.FormatInfo.Components;
+ int rhsComponents = rhs.FormatInfo.Components;
+
+ if (lhsComponents == 4 && rhsComponents == 4)
+ {
+ return swizzleLhs == swizzleRhs;
+ }
+
+ // Swizzles after the number of components a format defines are "undefined".
+ // We allow these to not be equal under certain circumstances.
+ // This can only happen when there are less than 4 components in a format.
+ // It tends to happen when float depth textures are sampled.
+
+ bool lhsDefined = (swizzleLhs - SwizzleComponent.Red) < lhsComponents;
+ bool rhsDefined = (swizzleRhs - SwizzleComponent.Red) < rhsComponents;
+
+ if (lhsDefined == rhsDefined)
+ {
+ // If both are undefined, return true. Otherwise just check if they're equal.
+ return lhsDefined ? swizzleLhs == swizzleRhs : true;
+ }
+ else
+ {
+ SwizzleComponent defined = lhsDefined ? swizzleLhs : swizzleRhs;
+ SwizzleComponent undefined = lhsDefined ? swizzleRhs : swizzleLhs;
+
+ // Undefined swizzle can be matched by a forced value (0, 1), exact equality, or expected value.
+ // For example, R___ matches R001, RGBA but not RBGA.
+ return defined == undefined || defined < SwizzleComponent.Red || defined == SwizzleComponent.Red + component;
+ }
+ }
+
///
/// Checks if the texture shader sampling parameters of two texture informations match.
///
@@ -406,10 +449,10 @@ namespace Ryujinx.Graphics.Gpu.Image
public static bool SamplerParamsMatches(TextureInfo lhs, TextureInfo rhs)
{
return lhs.DepthStencilMode == rhs.DepthStencilMode &&
- lhs.SwizzleR == rhs.SwizzleR &&
- lhs.SwizzleG == rhs.SwizzleG &&
- lhs.SwizzleB == rhs.SwizzleB &&
- lhs.SwizzleA == rhs.SwizzleA;
+ SwizzleComponentMatches(lhs, rhs, lhs.SwizzleR, rhs.SwizzleR, 0) &&
+ SwizzleComponentMatches(lhs, rhs, lhs.SwizzleG, rhs.SwizzleG, 1) &&
+ SwizzleComponentMatches(lhs, rhs, lhs.SwizzleB, rhs.SwizzleB, 2) &&
+ SwizzleComponentMatches(lhs, rhs, lhs.SwizzleA, rhs.SwizzleA, 3);
}
///
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
index 0b1d38d109..f8720695da 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
@@ -398,7 +398,7 @@ namespace Ryujinx.Graphics.Gpu.Image
// While upscaling works for all targets defined by IsUpscaleCompatible, we additionally blacklist targets here that
// may have undesirable results (upscaling blur textures) or simply waste GPU resources (upscaling texture atlas).
- if (!(info.FormatInfo.Format.IsDepthOrStencil() || info.FormatInfo.Format.HasOneComponent()))
+ if (!(info.FormatInfo.Format.IsDepthOrStencil() || info.FormatInfo.Components == 1))
{
// Discount square textures that aren't depth-stencil like. (excludes game textures, cubemap faces, most 3D texture LUT, texture atlas)
// Detect if the texture is possibly square. Widths may be aligned, so to remove the uncertainty we align both the width and height.
@@ -1037,11 +1037,11 @@ namespace Ryujinx.Graphics.Gpu.Image
{
if (formatInfo.Format.IsAstcUnorm())
{
- formatInfo = new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4);
+ formatInfo = new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4, 4);
}
else if (formatInfo.Format.IsAstcSrgb())
{
- formatInfo = new FormatInfo(Format.R8G8B8A8Srgb, 1, 1, 4);
+ formatInfo = new FormatInfo(Format.R8G8B8A8Srgb, 1, 1, 4, 4);
}
}
@@ -1052,12 +1052,12 @@ namespace Ryujinx.Graphics.Gpu.Image
// The shader will need the appropriate conversion code to compensate.
switch (formatInfo.Format)
{
- case Format.R8Snorm: formatInfo = new FormatInfo(Format.R8Sint, 1, 1, 1); break;
- case Format.R16Snorm: formatInfo = new FormatInfo(Format.R16Sint, 1, 1, 2); break;
- case Format.R8G8Snorm: formatInfo = new FormatInfo(Format.R8G8Sint, 1, 1, 2); break;
- case Format.R16G16Snorm: formatInfo = new FormatInfo(Format.R16G16Sint, 1, 1, 4); break;
- case Format.R8G8B8A8Snorm: formatInfo = new FormatInfo(Format.R8G8B8A8Sint, 1, 1, 4); break;
- case Format.R16G16B16A16Snorm: formatInfo = new FormatInfo(Format.R16G16B16A16Sint, 1, 1, 8); break;
+ case Format.R8Snorm: formatInfo = new FormatInfo(Format.R8Sint, 1, 1, 1, 1); break;
+ case Format.R16Snorm: formatInfo = new FormatInfo(Format.R16Sint, 1, 1, 2, 1); break;
+ case Format.R8G8Snorm: formatInfo = new FormatInfo(Format.R8G8Sint, 1, 1, 2, 2); break;
+ case Format.R16G16Snorm: formatInfo = new FormatInfo(Format.R16G16Sint, 1, 1, 4, 2); break;
+ case Format.R8G8B8A8Snorm: formatInfo = new FormatInfo(Format.R8G8B8A8Sint, 1, 1, 4, 4); break;
+ case Format.R16G16B16A16Snorm: formatInfo = new FormatInfo(Format.R16G16B16A16Sint, 1, 1, 8, 4); break;
}
}
diff --git a/Ryujinx.Graphics.Gpu/State/RtFormat.cs b/Ryujinx.Graphics.Gpu/State/RtFormat.cs
index ffd2492b64..f20ad2cdaf 100644
--- a/Ryujinx.Graphics.Gpu/State/RtFormat.cs
+++ b/Ryujinx.Graphics.Gpu/State/RtFormat.cs
@@ -81,66 +81,66 @@ namespace Ryujinx.Graphics.Gpu.State
{
return format switch
{
- RtFormat.D32Float => new FormatInfo(Format.D32Float, 1, 1, 4),
- RtFormat.D16Unorm => new FormatInfo(Format.D16Unorm, 1, 1, 2),
- RtFormat.D24UnormS8Uint => new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4),
- RtFormat.D24Unorm => new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4),
- RtFormat.S8UintD24Unorm => new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4),
- RtFormat.S8Uint => new FormatInfo(Format.S8Uint, 1, 1, 1),
- RtFormat.D32FloatS8Uint => new FormatInfo(Format.D32FloatS8Uint, 1, 1, 8),
- RtFormat.R32G32B32A32Float => new FormatInfo(Format.R32G32B32A32Float, 1, 1, 16),
- RtFormat.R32G32B32A32Sint => new FormatInfo(Format.R32G32B32A32Sint, 1, 1, 16),
- RtFormat.R32G32B32A32Uint => new FormatInfo(Format.R32G32B32A32Uint, 1, 1, 16),
- RtFormat.R32G32B32X32Float => new FormatInfo(Format.R32G32B32A32Float, 1, 1, 16),
- RtFormat.R32G32B32X32Sint => new FormatInfo(Format.R32G32B32A32Sint, 1, 1, 16),
- RtFormat.R32G32B32X32Uint => new FormatInfo(Format.R32G32B32A32Uint, 1, 1, 16),
- RtFormat.R16G16B16X16Unorm => new FormatInfo(Format.R16G16B16A16Unorm, 1, 1, 8),
- RtFormat.R16G16B16X16Snorm => new FormatInfo(Format.R16G16B16A16Snorm, 1, 1, 8),
- RtFormat.R16G16B16X16Sint => new FormatInfo(Format.R16G16B16A16Sint, 1, 1, 8),
- RtFormat.R16G16B16X16Uint => new FormatInfo(Format.R16G16B16A16Uint, 1, 1, 8),
- RtFormat.R16G16B16A16Float => new FormatInfo(Format.R16G16B16A16Float, 1, 1, 8),
- RtFormat.R32G32Float => new FormatInfo(Format.R32G32Float, 1, 1, 8),
- RtFormat.R32G32Sint => new FormatInfo(Format.R32G32Sint, 1, 1, 8),
- RtFormat.R32G32Uint => new FormatInfo(Format.R32G32Uint, 1, 1, 8),
- RtFormat.R16G16B16X16Float => new FormatInfo(Format.R16G16B16A16Float, 1, 1, 8),
- RtFormat.B8G8R8A8Unorm => new FormatInfo(Format.B8G8R8A8Unorm, 1, 1, 4),
- RtFormat.B8G8R8A8Srgb => new FormatInfo(Format.B8G8R8A8Srgb, 1, 1, 4),
- RtFormat.R10G10B10A2Unorm => new FormatInfo(Format.R10G10B10A2Unorm, 1, 1, 4),
- RtFormat.R10G10B10A2Uint => new FormatInfo(Format.R10G10B10A2Uint, 1, 1, 4),
- RtFormat.R8G8B8A8Unorm => new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4),
- RtFormat.R8G8B8A8Srgb => new FormatInfo(Format.R8G8B8A8Srgb, 1, 1, 4),
- RtFormat.R8G8B8X8Snorm => new FormatInfo(Format.R8G8B8A8Snorm, 1, 1, 4),
- RtFormat.R8G8B8X8Sint => new FormatInfo(Format.R8G8B8A8Sint, 1, 1, 4),
- RtFormat.R8G8B8X8Uint => new FormatInfo(Format.R8G8B8A8Uint, 1, 1, 4),
- RtFormat.R16G16Unorm => new FormatInfo(Format.R16G16Unorm, 1, 1, 4),
- RtFormat.R16G16Snorm => new FormatInfo(Format.R16G16Snorm, 1, 1, 4),
- RtFormat.R16G16Sint => new FormatInfo(Format.R16G16Sint, 1, 1, 4),
- RtFormat.R16G16Uint => new FormatInfo(Format.R16G16Uint, 1, 1, 4),
- RtFormat.R16G16Float => new FormatInfo(Format.R16G16Float, 1, 1, 4),
- RtFormat.R11G11B10Float => new FormatInfo(Format.R11G11B10Float, 1, 1, 4),
- RtFormat.R32Sint => new FormatInfo(Format.R32Sint, 1, 1, 4),
- RtFormat.R32Uint => new FormatInfo(Format.R32Uint, 1, 1, 4),
- RtFormat.R32Float => new FormatInfo(Format.R32Float, 1, 1, 4),
- RtFormat.B8G8R8X8Unorm => new FormatInfo(Format.B8G8R8A8Unorm, 1, 1, 4),
- RtFormat.B8G8R8X8Srgb => new FormatInfo(Format.B8G8R8A8Srgb, 1, 1, 4),
- RtFormat.B5G6R5Unorm => new FormatInfo(Format.B5G6R5Unorm, 1, 1, 2),
- RtFormat.B5G5R5A1Unorm => new FormatInfo(Format.B5G5R5A1Unorm, 1, 1, 2),
- RtFormat.R8G8Unorm => new FormatInfo(Format.R8G8Unorm, 1, 1, 2),
- RtFormat.R8G8Snorm => new FormatInfo(Format.R8G8Snorm, 1, 1, 2),
- RtFormat.R8G8Sint => new FormatInfo(Format.R8G8Sint, 1, 1, 2),
- RtFormat.R8G8Uint => new FormatInfo(Format.R8G8Uint, 1, 1, 2),
- RtFormat.R16Unorm => new FormatInfo(Format.R16Unorm, 1, 1, 2),
- RtFormat.R16Snorm => new FormatInfo(Format.R16Snorm, 1, 1, 2),
- RtFormat.R16Sint => new FormatInfo(Format.R16Sint, 1, 1, 2),
- RtFormat.R16Uint => new FormatInfo(Format.R16Uint, 1, 1, 2),
- RtFormat.R16Float => new FormatInfo(Format.R16Float, 1, 1, 2),
- RtFormat.R8Unorm => new FormatInfo(Format.R8Unorm, 1, 1, 1),
- RtFormat.R8Snorm => new FormatInfo(Format.R8Snorm, 1, 1, 1),
- RtFormat.R8Sint => new FormatInfo(Format.R8Sint, 1, 1, 1),
- RtFormat.R8Uint => new FormatInfo(Format.R8Uint, 1, 1, 1),
- RtFormat.B5G5R5X1Unorm => new FormatInfo(Format.B5G5R5X1Unorm, 1, 1, 2),
- RtFormat.R8G8B8X8Unorm => new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4),
- RtFormat.R8G8B8X8Srgb => new FormatInfo(Format.R8G8B8A8Srgb, 1, 1, 4),
+ RtFormat.D32Float => new FormatInfo(Format.D32Float, 1, 1, 4, 1),
+ RtFormat.D16Unorm => new FormatInfo(Format.D16Unorm, 1, 1, 2, 1),
+ RtFormat.D24UnormS8Uint => new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4, 2),
+ RtFormat.D24Unorm => new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4, 1),
+ RtFormat.S8UintD24Unorm => new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4, 2),
+ RtFormat.S8Uint => new FormatInfo(Format.S8Uint, 1, 1, 1, 1),
+ RtFormat.D32FloatS8Uint => new FormatInfo(Format.D32FloatS8Uint, 1, 1, 8, 2),
+ RtFormat.R32G32B32A32Float => new FormatInfo(Format.R32G32B32A32Float, 1, 1, 16, 4),
+ RtFormat.R32G32B32A32Sint => new FormatInfo(Format.R32G32B32A32Sint, 1, 1, 16, 4),
+ RtFormat.R32G32B32A32Uint => new FormatInfo(Format.R32G32B32A32Uint, 1, 1, 16, 4),
+ RtFormat.R32G32B32X32Float => new FormatInfo(Format.R32G32B32A32Float, 1, 1, 16, 4),
+ RtFormat.R32G32B32X32Sint => new FormatInfo(Format.R32G32B32A32Sint, 1, 1, 16, 4),
+ RtFormat.R32G32B32X32Uint => new FormatInfo(Format.R32G32B32A32Uint, 1, 1, 16, 4),
+ RtFormat.R16G16B16X16Unorm => new FormatInfo(Format.R16G16B16A16Unorm, 1, 1, 8, 4),
+ RtFormat.R16G16B16X16Snorm => new FormatInfo(Format.R16G16B16A16Snorm, 1, 1, 8, 4),
+ RtFormat.R16G16B16X16Sint => new FormatInfo(Format.R16G16B16A16Sint, 1, 1, 8, 4),
+ RtFormat.R16G16B16X16Uint => new FormatInfo(Format.R16G16B16A16Uint, 1, 1, 8, 4),
+ RtFormat.R16G16B16A16Float => new FormatInfo(Format.R16G16B16A16Float, 1, 1, 8, 4),
+ RtFormat.R32G32Float => new FormatInfo(Format.R32G32Float, 1, 1, 8, 2),
+ RtFormat.R32G32Sint => new FormatInfo(Format.R32G32Sint, 1, 1, 8, 2),
+ RtFormat.R32G32Uint => new FormatInfo(Format.R32G32Uint, 1, 1, 8, 2),
+ RtFormat.R16G16B16X16Float => new FormatInfo(Format.R16G16B16A16Float, 1, 1, 8, 4),
+ RtFormat.B8G8R8A8Unorm => new FormatInfo(Format.B8G8R8A8Unorm, 1, 1, 4, 4),
+ RtFormat.B8G8R8A8Srgb => new FormatInfo(Format.B8G8R8A8Srgb, 1, 1, 4, 4),
+ RtFormat.R10G10B10A2Unorm => new FormatInfo(Format.R10G10B10A2Unorm, 1, 1, 4, 4),
+ RtFormat.R10G10B10A2Uint => new FormatInfo(Format.R10G10B10A2Uint, 1, 1, 4, 4),
+ RtFormat.R8G8B8A8Unorm => new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4, 4),
+ RtFormat.R8G8B8A8Srgb => new FormatInfo(Format.R8G8B8A8Srgb, 1, 1, 4, 4),
+ RtFormat.R8G8B8X8Snorm => new FormatInfo(Format.R8G8B8A8Snorm, 1, 1, 4, 4),
+ RtFormat.R8G8B8X8Sint => new FormatInfo(Format.R8G8B8A8Sint, 1, 1, 4, 4),
+ RtFormat.R8G8B8X8Uint => new FormatInfo(Format.R8G8B8A8Uint, 1, 1, 4, 4),
+ RtFormat.R16G16Unorm => new FormatInfo(Format.R16G16Unorm, 1, 1, 4, 2),
+ RtFormat.R16G16Snorm => new FormatInfo(Format.R16G16Snorm, 1, 1, 4, 2),
+ RtFormat.R16G16Sint => new FormatInfo(Format.R16G16Sint, 1, 1, 4, 2),
+ RtFormat.R16G16Uint => new FormatInfo(Format.R16G16Uint, 1, 1, 4, 2),
+ RtFormat.R16G16Float => new FormatInfo(Format.R16G16Float, 1, 1, 4, 2),
+ RtFormat.R11G11B10Float => new FormatInfo(Format.R11G11B10Float, 1, 1, 4, 3),
+ RtFormat.R32Sint => new FormatInfo(Format.R32Sint, 1, 1, 4, 1),
+ RtFormat.R32Uint => new FormatInfo(Format.R32Uint, 1, 1, 4, 1),
+ RtFormat.R32Float => new FormatInfo(Format.R32Float, 1, 1, 4, 1),
+ RtFormat.B8G8R8X8Unorm => new FormatInfo(Format.B8G8R8A8Unorm, 1, 1, 4, 4),
+ RtFormat.B8G8R8X8Srgb => new FormatInfo(Format.B8G8R8A8Srgb, 1, 1, 4, 4),
+ RtFormat.B5G6R5Unorm => new FormatInfo(Format.B5G6R5Unorm, 1, 1, 2, 3),
+ RtFormat.B5G5R5A1Unorm => new FormatInfo(Format.B5G5R5A1Unorm, 1, 1, 2, 4),
+ RtFormat.R8G8Unorm => new FormatInfo(Format.R8G8Unorm, 1, 1, 2, 2),
+ RtFormat.R8G8Snorm => new FormatInfo(Format.R8G8Snorm, 1, 1, 2, 2),
+ RtFormat.R8G8Sint => new FormatInfo(Format.R8G8Sint, 1, 1, 2, 2),
+ RtFormat.R8G8Uint => new FormatInfo(Format.R8G8Uint, 1, 1, 2, 2),
+ RtFormat.R16Unorm => new FormatInfo(Format.R16Unorm, 1, 1, 2, 1),
+ RtFormat.R16Snorm => new FormatInfo(Format.R16Snorm, 1, 1, 2, 1),
+ RtFormat.R16Sint => new FormatInfo(Format.R16Sint, 1, 1, 2, 1),
+ RtFormat.R16Uint => new FormatInfo(Format.R16Uint, 1, 1, 2, 1),
+ RtFormat.R16Float => new FormatInfo(Format.R16Float, 1, 1, 2, 1),
+ RtFormat.R8Unorm => new FormatInfo(Format.R8Unorm, 1, 1, 1, 1),
+ RtFormat.R8Snorm => new FormatInfo(Format.R8Snorm, 1, 1, 1, 1),
+ RtFormat.R8Sint => new FormatInfo(Format.R8Sint, 1, 1, 1, 1),
+ RtFormat.R8Uint => new FormatInfo(Format.R8Uint, 1, 1, 1, 1),
+ RtFormat.B5G5R5X1Unorm => new FormatInfo(Format.B5G5R5X1Unorm, 1, 1, 2, 4),
+ RtFormat.R8G8B8X8Unorm => new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4, 4),
+ RtFormat.R8G8B8X8Srgb => new FormatInfo(Format.R8G8B8A8Srgb, 1, 1, 4, 4),
_ => FormatInfo.Default
};
}
diff --git a/Ryujinx.Graphics.Gpu/Window.cs b/Ryujinx.Graphics.Gpu/Window.cs
index 10ee74bec7..cf5c01efc9 100644
--- a/Ryujinx.Graphics.Gpu/Window.cs
+++ b/Ryujinx.Graphics.Gpu/Window.cs
@@ -112,7 +112,7 @@ namespace Ryujinx.Graphics.Gpu
Action