Allow swizzles to match with "undefined" components (#1538)

* Add swizzle matching rules.

Improves rules which try to match incompatible formats as perfect, such as D32 float -> R32 float.

Remove Format.HasOneComponent, since this information is now available via the FormatInfo struct.

* Fix this rule.

* Update component counts for depth formats.
This commit is contained in:
riperiperi 2020-09-11 00:48:48 +01:00 committed by GitHub
parent 5d69d9103e
commit 3d055da5fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 222 additions and 205 deletions

View File

@ -341,38 +341,5 @@ namespace Ryujinx.Graphics.GAL
{ {
return format.IsUint() || format.IsSint(); return format.IsUint() || format.IsSint();
} }
/// <summary>
/// Checks if the texture format only has one component.
/// </summary>
/// <param name="format">Texture format</param>
/// <returns>True if the texture format only has one component, false otherwise</returns>
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;
}
} }
} }

View File

@ -10,7 +10,7 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <summary> /// <summary>
/// A default, generic RGBA8 texture format. /// A default, generic RGBA8 texture format.
/// </summary> /// </summary>
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);
/// <summary> /// <summary>
/// The format of the texture data. /// The format of the texture data.
@ -38,6 +38,11 @@ namespace Ryujinx.Graphics.Gpu.Image
/// </summary> /// </summary>
public int BytesPerPixel { get; } public int BytesPerPixel { get; }
/// <summary>
/// The maximum number of components this format has defined (in RGBA order).
/// </summary>
public int Components { get; }
/// <summary> /// <summary>
/// Whenever or not the texture format is a compressed format. Determined from block size. /// Whenever or not the texture format is a compressed format. Determined from block size.
/// </summary> /// </summary>
@ -54,12 +59,14 @@ namespace Ryujinx.Graphics.Gpu.Image
Format format, Format format,
int blockWidth, int blockWidth,
int blockHeight, int blockHeight,
int bytesPerPixel) int bytesPerPixel,
int components)
{ {
Format = format; Format = format;
BlockWidth = blockWidth; BlockWidth = blockWidth;
BlockHeight = blockHeight; BlockHeight = blockHeight;
BytesPerPixel = bytesPerPixel; BytesPerPixel = bytesPerPixel;
Components = components;
} }
} }
} }

View File

@ -10,102 +10,102 @@ namespace Ryujinx.Graphics.Gpu.Image
{ {
private static Dictionary<uint, FormatInfo> _textureFormats = new Dictionary<uint, FormatInfo>() private static Dictionary<uint, FormatInfo> _textureFormats = new Dictionary<uint, FormatInfo>()
{ {
{ 0x2491d, new FormatInfo(Format.R8Unorm, 1, 1, 1) }, { 0x2491d, new FormatInfo(Format.R8Unorm, 1, 1, 1, 1) },
{ 0x1249d, new FormatInfo(Format.R8Snorm, 1, 1, 1) }, { 0x1249d, new FormatInfo(Format.R8Snorm, 1, 1, 1, 1) },
{ 0x4921d, new FormatInfo(Format.R8Uint, 1, 1, 1) }, { 0x4921d, new FormatInfo(Format.R8Uint, 1, 1, 1, 1) },
{ 0x36d9d, new FormatInfo(Format.R8Sint, 1, 1, 1) }, { 0x36d9d, new FormatInfo(Format.R8Sint, 1, 1, 1, 1) },
{ 0x7ff9b, new FormatInfo(Format.R16Float, 1, 1, 2) }, { 0x7ff9b, new FormatInfo(Format.R16Float, 1, 1, 2, 1) },
{ 0x2491b, new FormatInfo(Format.R16Unorm, 1, 1, 2) }, { 0x2491b, new FormatInfo(Format.R16Unorm, 1, 1, 2, 1) },
{ 0x1249b, new FormatInfo(Format.R16Snorm, 1, 1, 2) }, { 0x1249b, new FormatInfo(Format.R16Snorm, 1, 1, 2, 1) },
{ 0x4921b, new FormatInfo(Format.R16Uint, 1, 1, 2) }, { 0x4921b, new FormatInfo(Format.R16Uint, 1, 1, 2, 1) },
{ 0x36d9b, new FormatInfo(Format.R16Sint, 1, 1, 2) }, { 0x36d9b, new FormatInfo(Format.R16Sint, 1, 1, 2, 1) },
{ 0x7ff8f, new FormatInfo(Format.R32Float, 1, 1, 4) }, { 0x7ff8f, new FormatInfo(Format.R32Float, 1, 1, 4, 1) },
{ 0x4920f, new FormatInfo(Format.R32Uint, 1, 1, 4) }, { 0x4920f, new FormatInfo(Format.R32Uint, 1, 1, 4, 1) },
{ 0x36d8f, new FormatInfo(Format.R32Sint, 1, 1, 4) }, { 0x36d8f, new FormatInfo(Format.R32Sint, 1, 1, 4, 1) },
{ 0x24918, new FormatInfo(Format.R8G8Unorm, 1, 1, 2) }, { 0x24918, new FormatInfo(Format.R8G8Unorm, 1, 1, 2, 2) },
{ 0x12498, new FormatInfo(Format.R8G8Snorm, 1, 1, 2) }, { 0x12498, new FormatInfo(Format.R8G8Snorm, 1, 1, 2, 2) },
{ 0x49218, new FormatInfo(Format.R8G8Uint, 1, 1, 2) }, { 0x49218, new FormatInfo(Format.R8G8Uint, 1, 1, 2, 2) },
{ 0x36d98, new FormatInfo(Format.R8G8Sint, 1, 1, 2) }, { 0x36d98, new FormatInfo(Format.R8G8Sint, 1, 1, 2, 2) },
{ 0x7ff8c, new FormatInfo(Format.R16G16Float, 1, 1, 4) }, { 0x7ff8c, new FormatInfo(Format.R16G16Float, 1, 1, 4, 2) },
{ 0x2490c, new FormatInfo(Format.R16G16Unorm, 1, 1, 4) }, { 0x2490c, new FormatInfo(Format.R16G16Unorm, 1, 1, 4, 2) },
{ 0x1248c, new FormatInfo(Format.R16G16Snorm, 1, 1, 4) }, { 0x1248c, new FormatInfo(Format.R16G16Snorm, 1, 1, 4, 2) },
{ 0x4920c, new FormatInfo(Format.R16G16Uint, 1, 1, 4) }, { 0x4920c, new FormatInfo(Format.R16G16Uint, 1, 1, 4, 2) },
{ 0x36d8c, new FormatInfo(Format.R16G16Sint, 1, 1, 4) }, { 0x36d8c, new FormatInfo(Format.R16G16Sint, 1, 1, 4, 2) },
{ 0x7ff84, new FormatInfo(Format.R32G32Float, 1, 1, 8) }, { 0x7ff84, new FormatInfo(Format.R32G32Float, 1, 1, 8, 2) },
{ 0x49204, new FormatInfo(Format.R32G32Uint, 1, 1, 8) }, { 0x49204, new FormatInfo(Format.R32G32Uint, 1, 1, 8, 2) },
{ 0x36d84, new FormatInfo(Format.R32G32Sint, 1, 1, 8) }, { 0x36d84, new FormatInfo(Format.R32G32Sint, 1, 1, 8, 2) },
{ 0x7ff82, new FormatInfo(Format.R32G32B32Float, 1, 1, 12) }, { 0x7ff82, new FormatInfo(Format.R32G32B32Float, 1, 1, 12, 3) },
{ 0x49202, new FormatInfo(Format.R32G32B32Uint, 1, 1, 12) }, { 0x49202, new FormatInfo(Format.R32G32B32Uint, 1, 1, 12, 3) },
{ 0x36d82, new FormatInfo(Format.R32G32B32Sint, 1, 1, 12) }, { 0x36d82, new FormatInfo(Format.R32G32B32Sint, 1, 1, 12, 3) },
{ 0x24908, new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4) }, { 0x24908, new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4, 4) },
{ 0x12488, new FormatInfo(Format.R8G8B8A8Snorm, 1, 1, 4) }, { 0x12488, new FormatInfo(Format.R8G8B8A8Snorm, 1, 1, 4, 4) },
{ 0x49208, new FormatInfo(Format.R8G8B8A8Uint, 1, 1, 4) }, { 0x49208, new FormatInfo(Format.R8G8B8A8Uint, 1, 1, 4, 4) },
{ 0x36d88, new FormatInfo(Format.R8G8B8A8Sint, 1, 1, 4) }, { 0x36d88, new FormatInfo(Format.R8G8B8A8Sint, 1, 1, 4, 4) },
{ 0x7ff83, new FormatInfo(Format.R16G16B16A16Float, 1, 1, 8) }, { 0x7ff83, new FormatInfo(Format.R16G16B16A16Float, 1, 1, 8, 4) },
{ 0x24903, new FormatInfo(Format.R16G16B16A16Unorm, 1, 1, 8) }, { 0x24903, new FormatInfo(Format.R16G16B16A16Unorm, 1, 1, 8, 4) },
{ 0x12483, new FormatInfo(Format.R16G16B16A16Snorm, 1, 1, 8) }, { 0x12483, new FormatInfo(Format.R16G16B16A16Snorm, 1, 1, 8, 4) },
{ 0x49203, new FormatInfo(Format.R16G16B16A16Uint, 1, 1, 8) }, { 0x49203, new FormatInfo(Format.R16G16B16A16Uint, 1, 1, 8, 4) },
{ 0x36d83, new FormatInfo(Format.R16G16B16A16Sint, 1, 1, 8) }, { 0x36d83, new FormatInfo(Format.R16G16B16A16Sint, 1, 1, 8, 4) },
{ 0x7ff81, new FormatInfo(Format.R32G32B32A32Float, 1, 1, 16) }, { 0x7ff81, new FormatInfo(Format.R32G32B32A32Float, 1, 1, 16, 4) },
{ 0x49201, new FormatInfo(Format.R32G32B32A32Uint, 1, 1, 16) }, { 0x49201, new FormatInfo(Format.R32G32B32A32Uint, 1, 1, 16, 4) },
{ 0x36d81, new FormatInfo(Format.R32G32B32A32Sint, 1, 1, 16) }, { 0x36d81, new FormatInfo(Format.R32G32B32A32Sint, 1, 1, 16, 4) },
{ 0x2493a, new FormatInfo(Format.D16Unorm, 1, 1, 2) }, { 0x2493a, new FormatInfo(Format.D16Unorm, 1, 1, 2, 1) },
{ 0x7ffaf, new FormatInfo(Format.D32Float, 1, 1, 4) }, { 0x7ffaf, new FormatInfo(Format.D32Float, 1, 1, 4, 1) },
{ 0x24a0e, new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4) }, { 0x24a0e, new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4, 2) },
{ 0x24a29, new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4) }, { 0x24a29, new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4, 2) },
{ 0x25385, new FormatInfo(Format.D32FloatS8Uint, 1, 1, 8) }, { 0x25385, new FormatInfo(Format.D32FloatS8Uint, 1, 1, 8, 2) },
{ 0x253b0, new FormatInfo(Format.D32FloatS8Uint, 1, 1, 8) }, { 0x253b0, new FormatInfo(Format.D32FloatS8Uint, 1, 1, 8, 2) },
{ 0xa4908, new FormatInfo(Format.R8G8B8A8Srgb, 1, 1, 4) }, { 0xa4908, new FormatInfo(Format.R8G8B8A8Srgb, 1, 1, 4, 4) },
{ 0x24912, new FormatInfo(Format.R4G4B4A4Unorm, 1, 1, 2) }, { 0x24912, new FormatInfo(Format.R4G4B4A4Unorm, 1, 1, 2, 4) },
{ 0x24914, new FormatInfo(Format.R5G5B5A1Unorm, 1, 1, 2) }, { 0x24914, new FormatInfo(Format.R5G5B5A1Unorm, 1, 1, 2, 4) },
{ 0x24915, new FormatInfo(Format.R5G6B5Unorm, 1, 1, 2) }, { 0x24915, new FormatInfo(Format.R5G6B5Unorm, 1, 1, 2, 3) },
{ 0x24909, new FormatInfo(Format.R10G10B10A2Unorm, 1, 1, 4) }, { 0x24909, new FormatInfo(Format.R10G10B10A2Unorm, 1, 1, 4, 4) },
{ 0x49209, new FormatInfo(Format.R10G10B10A2Uint, 1, 1, 4) }, { 0x49209, new FormatInfo(Format.R10G10B10A2Uint, 1, 1, 4, 4) },
{ 0x7ffa1, new FormatInfo(Format.R11G11B10Float, 1, 1, 4) }, { 0x7ffa1, new FormatInfo(Format.R11G11B10Float, 1, 1, 4, 3) },
{ 0x7ffa0, new FormatInfo(Format.R9G9B9E5Float, 1, 1, 4) }, { 0x7ffa0, new FormatInfo(Format.R9G9B9E5Float, 1, 1, 4, 4) },
{ 0x24924, new FormatInfo(Format.Bc1RgbaUnorm, 4, 4, 8) }, { 0x24924, new FormatInfo(Format.Bc1RgbaUnorm, 4, 4, 8, 4) },
{ 0x24925, new FormatInfo(Format.Bc2Unorm, 4, 4, 16) }, { 0x24925, new FormatInfo(Format.Bc2Unorm, 4, 4, 16, 4) },
{ 0x24926, new FormatInfo(Format.Bc3Unorm, 4, 4, 16) }, { 0x24926, new FormatInfo(Format.Bc3Unorm, 4, 4, 16, 4) },
{ 0xa4924, new FormatInfo(Format.Bc1RgbaSrgb, 4, 4, 8) }, { 0xa4924, new FormatInfo(Format.Bc1RgbaSrgb, 4, 4, 8, 4) },
{ 0xa4925, new FormatInfo(Format.Bc2Srgb, 4, 4, 16) }, { 0xa4925, new FormatInfo(Format.Bc2Srgb, 4, 4, 16, 4) },
{ 0xa4926, new FormatInfo(Format.Bc3Srgb, 4, 4, 16) }, { 0xa4926, new FormatInfo(Format.Bc3Srgb, 4, 4, 16, 4) },
{ 0x24927, new FormatInfo(Format.Bc4Unorm, 4, 4, 8) }, { 0x24927, new FormatInfo(Format.Bc4Unorm, 4, 4, 8, 1) },
{ 0x124a7, new FormatInfo(Format.Bc4Snorm, 4, 4, 8) }, { 0x124a7, new FormatInfo(Format.Bc4Snorm, 4, 4, 8, 1) },
{ 0x24928, new FormatInfo(Format.Bc5Unorm, 4, 4, 16) }, { 0x24928, new FormatInfo(Format.Bc5Unorm, 4, 4, 16, 2) },
{ 0x124a8, new FormatInfo(Format.Bc5Snorm, 4, 4, 16) }, { 0x124a8, new FormatInfo(Format.Bc5Snorm, 4, 4, 16, 2) },
{ 0x24917, new FormatInfo(Format.Bc7Unorm, 4, 4, 16) }, { 0x24917, new FormatInfo(Format.Bc7Unorm, 4, 4, 16, 4) },
{ 0xa4917, new FormatInfo(Format.Bc7Srgb, 4, 4, 16) }, { 0xa4917, new FormatInfo(Format.Bc7Srgb, 4, 4, 16, 4) },
{ 0x7ff90, new FormatInfo(Format.Bc6HSfloat, 4, 4, 16) }, { 0x7ff90, new FormatInfo(Format.Bc6HSfloat, 4, 4, 16, 4) },
{ 0x7ff91, new FormatInfo(Format.Bc6HUfloat, 4, 4, 16) }, { 0x7ff91, new FormatInfo(Format.Bc6HUfloat, 4, 4, 16, 4) },
{ 0x24940, new FormatInfo(Format.Astc4x4Unorm, 4, 4, 16) }, { 0x24940, new FormatInfo(Format.Astc4x4Unorm, 4, 4, 16, 4) },
{ 0x24950, new FormatInfo(Format.Astc5x4Unorm, 5, 4, 16) }, { 0x24950, new FormatInfo(Format.Astc5x4Unorm, 5, 4, 16, 4) },
{ 0x24941, new FormatInfo(Format.Astc5x5Unorm, 5, 5, 16) }, { 0x24941, new FormatInfo(Format.Astc5x5Unorm, 5, 5, 16, 4) },
{ 0x24951, new FormatInfo(Format.Astc6x5Unorm, 6, 5, 16) }, { 0x24951, new FormatInfo(Format.Astc6x5Unorm, 6, 5, 16, 4) },
{ 0x24942, new FormatInfo(Format.Astc6x6Unorm, 6, 6, 16) }, { 0x24942, new FormatInfo(Format.Astc6x6Unorm, 6, 6, 16, 4) },
{ 0x24955, new FormatInfo(Format.Astc8x5Unorm, 8, 5, 16) }, { 0x24955, new FormatInfo(Format.Astc8x5Unorm, 8, 5, 16, 4) },
{ 0x24952, new FormatInfo(Format.Astc8x6Unorm, 8, 6, 16) }, { 0x24952, new FormatInfo(Format.Astc8x6Unorm, 8, 6, 16, 4) },
{ 0x24944, new FormatInfo(Format.Astc8x8Unorm, 8, 8, 16) }, { 0x24944, new FormatInfo(Format.Astc8x8Unorm, 8, 8, 16, 4) },
{ 0x24956, new FormatInfo(Format.Astc10x5Unorm, 10, 5, 16) }, { 0x24956, new FormatInfo(Format.Astc10x5Unorm, 10, 5, 16, 4) },
{ 0x24957, new FormatInfo(Format.Astc10x6Unorm, 10, 6, 16) }, { 0x24957, new FormatInfo(Format.Astc10x6Unorm, 10, 6, 16, 4) },
{ 0x24953, new FormatInfo(Format.Astc10x8Unorm, 10, 8, 16) }, { 0x24953, new FormatInfo(Format.Astc10x8Unorm, 10, 8, 16, 4) },
{ 0x24945, new FormatInfo(Format.Astc10x10Unorm, 10, 10, 16) }, { 0x24945, new FormatInfo(Format.Astc10x10Unorm, 10, 10, 16, 4) },
{ 0x24954, new FormatInfo(Format.Astc12x10Unorm, 12, 10, 16) }, { 0x24954, new FormatInfo(Format.Astc12x10Unorm, 12, 10, 16, 4) },
{ 0x24946, new FormatInfo(Format.Astc12x12Unorm, 12, 12, 16) }, { 0x24946, new FormatInfo(Format.Astc12x12Unorm, 12, 12, 16, 4) },
{ 0xa4940, new FormatInfo(Format.Astc4x4Srgb, 4, 4, 16) }, { 0xa4940, new FormatInfo(Format.Astc4x4Srgb, 4, 4, 16, 4) },
{ 0xa4950, new FormatInfo(Format.Astc5x4Srgb, 5, 4, 16) }, { 0xa4950, new FormatInfo(Format.Astc5x4Srgb, 5, 4, 16, 4) },
{ 0xa4941, new FormatInfo(Format.Astc5x5Srgb, 5, 5, 16) }, { 0xa4941, new FormatInfo(Format.Astc5x5Srgb, 5, 5, 16, 4) },
{ 0xa4951, new FormatInfo(Format.Astc6x5Srgb, 6, 5, 16) }, { 0xa4951, new FormatInfo(Format.Astc6x5Srgb, 6, 5, 16, 4) },
{ 0xa4942, new FormatInfo(Format.Astc6x6Srgb, 6, 6, 16) }, { 0xa4942, new FormatInfo(Format.Astc6x6Srgb, 6, 6, 16, 4) },
{ 0xa4955, new FormatInfo(Format.Astc8x5Srgb, 8, 5, 16) }, { 0xa4955, new FormatInfo(Format.Astc8x5Srgb, 8, 5, 16, 4) },
{ 0xa4952, new FormatInfo(Format.Astc8x6Srgb, 8, 6, 16) }, { 0xa4952, new FormatInfo(Format.Astc8x6Srgb, 8, 6, 16, 4) },
{ 0xa4944, new FormatInfo(Format.Astc8x8Srgb, 8, 8, 16) }, { 0xa4944, new FormatInfo(Format.Astc8x8Srgb, 8, 8, 16, 4) },
{ 0xa4956, new FormatInfo(Format.Astc10x5Srgb, 10, 5, 16) }, { 0xa4956, new FormatInfo(Format.Astc10x5Srgb, 10, 5, 16, 4) },
{ 0xa4957, new FormatInfo(Format.Astc10x6Srgb, 10, 6, 16) }, { 0xa4957, new FormatInfo(Format.Astc10x6Srgb, 10, 6, 16, 4) },
{ 0xa4953, new FormatInfo(Format.Astc10x8Srgb, 10, 8, 16) }, { 0xa4953, new FormatInfo(Format.Astc10x8Srgb, 10, 8, 16, 4) },
{ 0xa4945, new FormatInfo(Format.Astc10x10Srgb, 10, 10, 16) }, { 0xa4945, new FormatInfo(Format.Astc10x10Srgb, 10, 10, 16, 4) },
{ 0xa4954, new FormatInfo(Format.Astc12x10Srgb, 12, 10, 16) }, { 0xa4954, new FormatInfo(Format.Astc12x10Srgb, 12, 10, 16, 4) },
{ 0xa4946, new FormatInfo(Format.Astc12x12Srgb, 12, 12, 16) }, { 0xa4946, new FormatInfo(Format.Astc12x12Srgb, 12, 12, 16, 4) },
{ 0x24913, new FormatInfo(Format.A1B5G5R5Unorm, 1, 1, 2) } { 0x24913, new FormatInfo(Format.A1B5G5R5Unorm, 1, 1, 2, 4) }
}; };
private static Dictionary<ulong, Format> _attribFormats = new Dictionary<ulong, Format>() private static Dictionary<ulong, Format> _attribFormats = new Dictionary<ulong, Format>()

View File

@ -397,6 +397,49 @@ namespace Ryujinx.Graphics.Gpu.Image
return result ? TextureViewCompatibility.Full : TextureViewCompatibility.Incompatible; return result ? TextureViewCompatibility.Full : TextureViewCompatibility.Incompatible;
} }
/// <summary>
/// Checks if a swizzle component in two textures functionally match, taking into account if the components are defined.
/// </summary>
/// <param name="lhs">Texture information to compare</param>
/// <param name="rhs">Texture information to compare with</param>
/// <param name="swizzleLhs">Swizzle component for the first texture</param>
/// <param name="swizzleRhs">Swizzle component for the second texture</param>
/// <param name="component">Component index, starting at 0 for red</param>
/// <returns>True if the swizzle components functionally match, false othersize</returns>
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;
}
}
/// <summary> /// <summary>
/// Checks if the texture shader sampling parameters of two texture informations match. /// Checks if the texture shader sampling parameters of two texture informations match.
/// </summary> /// </summary>
@ -406,10 +449,10 @@ namespace Ryujinx.Graphics.Gpu.Image
public static bool SamplerParamsMatches(TextureInfo lhs, TextureInfo rhs) public static bool SamplerParamsMatches(TextureInfo lhs, TextureInfo rhs)
{ {
return lhs.DepthStencilMode == rhs.DepthStencilMode && return lhs.DepthStencilMode == rhs.DepthStencilMode &&
lhs.SwizzleR == rhs.SwizzleR && SwizzleComponentMatches(lhs, rhs, lhs.SwizzleR, rhs.SwizzleR, 0) &&
lhs.SwizzleG == rhs.SwizzleG && SwizzleComponentMatches(lhs, rhs, lhs.SwizzleG, rhs.SwizzleG, 1) &&
lhs.SwizzleB == rhs.SwizzleB && SwizzleComponentMatches(lhs, rhs, lhs.SwizzleB, rhs.SwizzleB, 2) &&
lhs.SwizzleA == rhs.SwizzleA; SwizzleComponentMatches(lhs, rhs, lhs.SwizzleA, rhs.SwizzleA, 3);
} }
/// <summary> /// <summary>

View File

@ -398,7 +398,7 @@ namespace Ryujinx.Graphics.Gpu.Image
// While upscaling works for all targets defined by IsUpscaleCompatible, we additionally blacklist targets here that // 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). // 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) // 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. // 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()) 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()) 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. // The shader will need the appropriate conversion code to compensate.
switch (formatInfo.Format) switch (formatInfo.Format)
{ {
case Format.R8Snorm: formatInfo = new FormatInfo(Format.R8Sint, 1, 1, 1); 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); 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); 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); 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); 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); break; case Format.R16G16B16A16Snorm: formatInfo = new FormatInfo(Format.R16G16B16A16Sint, 1, 1, 8, 4); break;
} }
} }

View File

@ -81,66 +81,66 @@ namespace Ryujinx.Graphics.Gpu.State
{ {
return format switch return format switch
{ {
RtFormat.D32Float => new FormatInfo(Format.D32Float, 1, 1, 4), RtFormat.D32Float => new FormatInfo(Format.D32Float, 1, 1, 4, 1),
RtFormat.D16Unorm => new FormatInfo(Format.D16Unorm, 1, 1, 2), RtFormat.D16Unorm => new FormatInfo(Format.D16Unorm, 1, 1, 2, 1),
RtFormat.D24UnormS8Uint => new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4), RtFormat.D24UnormS8Uint => new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4, 2),
RtFormat.D24Unorm => new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4), RtFormat.D24Unorm => new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4, 1),
RtFormat.S8UintD24Unorm => new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4), RtFormat.S8UintD24Unorm => new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4, 2),
RtFormat.S8Uint => new FormatInfo(Format.S8Uint, 1, 1, 1), RtFormat.S8Uint => new FormatInfo(Format.S8Uint, 1, 1, 1, 1),
RtFormat.D32FloatS8Uint => new FormatInfo(Format.D32FloatS8Uint, 1, 1, 8), RtFormat.D32FloatS8Uint => new FormatInfo(Format.D32FloatS8Uint, 1, 1, 8, 2),
RtFormat.R32G32B32A32Float => new FormatInfo(Format.R32G32B32A32Float, 1, 1, 16), RtFormat.R32G32B32A32Float => new FormatInfo(Format.R32G32B32A32Float, 1, 1, 16, 4),
RtFormat.R32G32B32A32Sint => new FormatInfo(Format.R32G32B32A32Sint, 1, 1, 16), RtFormat.R32G32B32A32Sint => new FormatInfo(Format.R32G32B32A32Sint, 1, 1, 16, 4),
RtFormat.R32G32B32A32Uint => new FormatInfo(Format.R32G32B32A32Uint, 1, 1, 16), RtFormat.R32G32B32A32Uint => new FormatInfo(Format.R32G32B32A32Uint, 1, 1, 16, 4),
RtFormat.R32G32B32X32Float => new FormatInfo(Format.R32G32B32A32Float, 1, 1, 16), RtFormat.R32G32B32X32Float => new FormatInfo(Format.R32G32B32A32Float, 1, 1, 16, 4),
RtFormat.R32G32B32X32Sint => new FormatInfo(Format.R32G32B32A32Sint, 1, 1, 16), RtFormat.R32G32B32X32Sint => new FormatInfo(Format.R32G32B32A32Sint, 1, 1, 16, 4),
RtFormat.R32G32B32X32Uint => new FormatInfo(Format.R32G32B32A32Uint, 1, 1, 16), RtFormat.R32G32B32X32Uint => new FormatInfo(Format.R32G32B32A32Uint, 1, 1, 16, 4),
RtFormat.R16G16B16X16Unorm => new FormatInfo(Format.R16G16B16A16Unorm, 1, 1, 8), RtFormat.R16G16B16X16Unorm => new FormatInfo(Format.R16G16B16A16Unorm, 1, 1, 8, 4),
RtFormat.R16G16B16X16Snorm => new FormatInfo(Format.R16G16B16A16Snorm, 1, 1, 8), RtFormat.R16G16B16X16Snorm => new FormatInfo(Format.R16G16B16A16Snorm, 1, 1, 8, 4),
RtFormat.R16G16B16X16Sint => new FormatInfo(Format.R16G16B16A16Sint, 1, 1, 8), RtFormat.R16G16B16X16Sint => new FormatInfo(Format.R16G16B16A16Sint, 1, 1, 8, 4),
RtFormat.R16G16B16X16Uint => new FormatInfo(Format.R16G16B16A16Uint, 1, 1, 8), RtFormat.R16G16B16X16Uint => new FormatInfo(Format.R16G16B16A16Uint, 1, 1, 8, 4),
RtFormat.R16G16B16A16Float => new FormatInfo(Format.R16G16B16A16Float, 1, 1, 8), RtFormat.R16G16B16A16Float => new FormatInfo(Format.R16G16B16A16Float, 1, 1, 8, 4),
RtFormat.R32G32Float => new FormatInfo(Format.R32G32Float, 1, 1, 8), RtFormat.R32G32Float => new FormatInfo(Format.R32G32Float, 1, 1, 8, 2),
RtFormat.R32G32Sint => new FormatInfo(Format.R32G32Sint, 1, 1, 8), RtFormat.R32G32Sint => new FormatInfo(Format.R32G32Sint, 1, 1, 8, 2),
RtFormat.R32G32Uint => new FormatInfo(Format.R32G32Uint, 1, 1, 8), RtFormat.R32G32Uint => new FormatInfo(Format.R32G32Uint, 1, 1, 8, 2),
RtFormat.R16G16B16X16Float => new FormatInfo(Format.R16G16B16A16Float, 1, 1, 8), RtFormat.R16G16B16X16Float => new FormatInfo(Format.R16G16B16A16Float, 1, 1, 8, 4),
RtFormat.B8G8R8A8Unorm => new FormatInfo(Format.B8G8R8A8Unorm, 1, 1, 4), RtFormat.B8G8R8A8Unorm => new FormatInfo(Format.B8G8R8A8Unorm, 1, 1, 4, 4),
RtFormat.B8G8R8A8Srgb => new FormatInfo(Format.B8G8R8A8Srgb, 1, 1, 4), RtFormat.B8G8R8A8Srgb => new FormatInfo(Format.B8G8R8A8Srgb, 1, 1, 4, 4),
RtFormat.R10G10B10A2Unorm => new FormatInfo(Format.R10G10B10A2Unorm, 1, 1, 4), RtFormat.R10G10B10A2Unorm => new FormatInfo(Format.R10G10B10A2Unorm, 1, 1, 4, 4),
RtFormat.R10G10B10A2Uint => new FormatInfo(Format.R10G10B10A2Uint, 1, 1, 4), RtFormat.R10G10B10A2Uint => new FormatInfo(Format.R10G10B10A2Uint, 1, 1, 4, 4),
RtFormat.R8G8B8A8Unorm => new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4), RtFormat.R8G8B8A8Unorm => new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4, 4),
RtFormat.R8G8B8A8Srgb => new FormatInfo(Format.R8G8B8A8Srgb, 1, 1, 4), RtFormat.R8G8B8A8Srgb => new FormatInfo(Format.R8G8B8A8Srgb, 1, 1, 4, 4),
RtFormat.R8G8B8X8Snorm => new FormatInfo(Format.R8G8B8A8Snorm, 1, 1, 4), RtFormat.R8G8B8X8Snorm => new FormatInfo(Format.R8G8B8A8Snorm, 1, 1, 4, 4),
RtFormat.R8G8B8X8Sint => new FormatInfo(Format.R8G8B8A8Sint, 1, 1, 4), RtFormat.R8G8B8X8Sint => new FormatInfo(Format.R8G8B8A8Sint, 1, 1, 4, 4),
RtFormat.R8G8B8X8Uint => new FormatInfo(Format.R8G8B8A8Uint, 1, 1, 4), RtFormat.R8G8B8X8Uint => new FormatInfo(Format.R8G8B8A8Uint, 1, 1, 4, 4),
RtFormat.R16G16Unorm => new FormatInfo(Format.R16G16Unorm, 1, 1, 4), RtFormat.R16G16Unorm => new FormatInfo(Format.R16G16Unorm, 1, 1, 4, 2),
RtFormat.R16G16Snorm => new FormatInfo(Format.R16G16Snorm, 1, 1, 4), RtFormat.R16G16Snorm => new FormatInfo(Format.R16G16Snorm, 1, 1, 4, 2),
RtFormat.R16G16Sint => new FormatInfo(Format.R16G16Sint, 1, 1, 4), RtFormat.R16G16Sint => new FormatInfo(Format.R16G16Sint, 1, 1, 4, 2),
RtFormat.R16G16Uint => new FormatInfo(Format.R16G16Uint, 1, 1, 4), RtFormat.R16G16Uint => new FormatInfo(Format.R16G16Uint, 1, 1, 4, 2),
RtFormat.R16G16Float => new FormatInfo(Format.R16G16Float, 1, 1, 4), RtFormat.R16G16Float => new FormatInfo(Format.R16G16Float, 1, 1, 4, 2),
RtFormat.R11G11B10Float => new FormatInfo(Format.R11G11B10Float, 1, 1, 4), RtFormat.R11G11B10Float => new FormatInfo(Format.R11G11B10Float, 1, 1, 4, 3),
RtFormat.R32Sint => new FormatInfo(Format.R32Sint, 1, 1, 4), RtFormat.R32Sint => new FormatInfo(Format.R32Sint, 1, 1, 4, 1),
RtFormat.R32Uint => new FormatInfo(Format.R32Uint, 1, 1, 4), RtFormat.R32Uint => new FormatInfo(Format.R32Uint, 1, 1, 4, 1),
RtFormat.R32Float => new FormatInfo(Format.R32Float, 1, 1, 4), RtFormat.R32Float => new FormatInfo(Format.R32Float, 1, 1, 4, 1),
RtFormat.B8G8R8X8Unorm => new FormatInfo(Format.B8G8R8A8Unorm, 1, 1, 4), RtFormat.B8G8R8X8Unorm => new FormatInfo(Format.B8G8R8A8Unorm, 1, 1, 4, 4),
RtFormat.B8G8R8X8Srgb => new FormatInfo(Format.B8G8R8A8Srgb, 1, 1, 4), RtFormat.B8G8R8X8Srgb => new FormatInfo(Format.B8G8R8A8Srgb, 1, 1, 4, 4),
RtFormat.B5G6R5Unorm => new FormatInfo(Format.B5G6R5Unorm, 1, 1, 2), RtFormat.B5G6R5Unorm => new FormatInfo(Format.B5G6R5Unorm, 1, 1, 2, 3),
RtFormat.B5G5R5A1Unorm => new FormatInfo(Format.B5G5R5A1Unorm, 1, 1, 2), RtFormat.B5G5R5A1Unorm => new FormatInfo(Format.B5G5R5A1Unorm, 1, 1, 2, 4),
RtFormat.R8G8Unorm => new FormatInfo(Format.R8G8Unorm, 1, 1, 2), RtFormat.R8G8Unorm => new FormatInfo(Format.R8G8Unorm, 1, 1, 2, 2),
RtFormat.R8G8Snorm => new FormatInfo(Format.R8G8Snorm, 1, 1, 2), RtFormat.R8G8Snorm => new FormatInfo(Format.R8G8Snorm, 1, 1, 2, 2),
RtFormat.R8G8Sint => new FormatInfo(Format.R8G8Sint, 1, 1, 2), RtFormat.R8G8Sint => new FormatInfo(Format.R8G8Sint, 1, 1, 2, 2),
RtFormat.R8G8Uint => new FormatInfo(Format.R8G8Uint, 1, 1, 2), RtFormat.R8G8Uint => new FormatInfo(Format.R8G8Uint, 1, 1, 2, 2),
RtFormat.R16Unorm => new FormatInfo(Format.R16Unorm, 1, 1, 2), RtFormat.R16Unorm => new FormatInfo(Format.R16Unorm, 1, 1, 2, 1),
RtFormat.R16Snorm => new FormatInfo(Format.R16Snorm, 1, 1, 2), RtFormat.R16Snorm => new FormatInfo(Format.R16Snorm, 1, 1, 2, 1),
RtFormat.R16Sint => new FormatInfo(Format.R16Sint, 1, 1, 2), RtFormat.R16Sint => new FormatInfo(Format.R16Sint, 1, 1, 2, 1),
RtFormat.R16Uint => new FormatInfo(Format.R16Uint, 1, 1, 2), RtFormat.R16Uint => new FormatInfo(Format.R16Uint, 1, 1, 2, 1),
RtFormat.R16Float => new FormatInfo(Format.R16Float, 1, 1, 2), RtFormat.R16Float => new FormatInfo(Format.R16Float, 1, 1, 2, 1),
RtFormat.R8Unorm => new FormatInfo(Format.R8Unorm, 1, 1, 1), RtFormat.R8Unorm => new FormatInfo(Format.R8Unorm, 1, 1, 1, 1),
RtFormat.R8Snorm => new FormatInfo(Format.R8Snorm, 1, 1, 1), RtFormat.R8Snorm => new FormatInfo(Format.R8Snorm, 1, 1, 1, 1),
RtFormat.R8Sint => new FormatInfo(Format.R8Sint, 1, 1, 1), RtFormat.R8Sint => new FormatInfo(Format.R8Sint, 1, 1, 1, 1),
RtFormat.R8Uint => new FormatInfo(Format.R8Uint, 1, 1, 1), RtFormat.R8Uint => new FormatInfo(Format.R8Uint, 1, 1, 1, 1),
RtFormat.B5G5R5X1Unorm => new FormatInfo(Format.B5G5R5X1Unorm, 1, 1, 2), RtFormat.B5G5R5X1Unorm => new FormatInfo(Format.B5G5R5X1Unorm, 1, 1, 2, 4),
RtFormat.R8G8B8X8Unorm => new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4), RtFormat.R8G8B8X8Unorm => new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4, 4),
RtFormat.R8G8B8X8Srgb => new FormatInfo(Format.R8G8B8A8Srgb, 1, 1, 4), RtFormat.R8G8B8X8Srgb => new FormatInfo(Format.R8G8B8A8Srgb, 1, 1, 4, 4),
_ => FormatInfo.Default _ => FormatInfo.Default
}; };
} }

View File

@ -112,7 +112,7 @@ namespace Ryujinx.Graphics.Gpu
Action<object> releaseCallback, Action<object> releaseCallback,
object userObj) object userObj)
{ {
FormatInfo formatInfo = new FormatInfo(format, 1, 1, bytesPerPixel); FormatInfo formatInfo = new FormatInfo(format, 1, 1, bytesPerPixel, 4);
TextureInfo info = new TextureInfo( TextureInfo info = new TextureInfo(
address, address,